<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for files.c
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include <boost/test/unit_test.hpp>

#include "Basics/StringBuffer.h"
#include "BasicsC/files.h"

using namespace triagens::basics;

// -----------------------------------------------------------------------------
// --SECTION--                                                 setup / tear-down
// -----------------------------------------------------------------------------

struct CFilesSetup {
  CFilesSetup () : _directory(TRI_UNKNOWN_MEM_ZONE) {
    BOOST_TEST_MESSAGE("setup files");

    _directory.appendText("/tmp/arangotest-");
    _directory.appendInteger((uint64_t) TRI_microtime());

    TRI_CreateDirectory(_directory.c_str());
  }

  ~CFilesSetup () {
    BOOST_TEST_MESSAGE("tear-down files");

    // let's be sure we delete the right stuff
    assert(_directory.length() > 10);
    assert(memcmp((void*) _directory.c_str(), (void*) "/tmp/arangotest-", 16) == 0);

    TRI_RemoveDirectory(_directory.c_str());
  }

  StringBuffer* writeFile (const char* blob) {
    static uint64_t counter = 0;

    StringBuffer* filename = new StringBuffer(TRI_UNKNOWN_MEM_ZONE);
    filename->appendText(_directory);
    filename->appendText("/tmp-");
    filename->appendInteger(++counter);

    int fd = TRI_OPEN(filename->c_str(), O_RDWR | O_CREAT);

    if (fd) {
      ::write(fd, &blob, strlen(blob));
      ::close(fd);
    }
    else {
      BOOST_CHECK_EQUAL(false, true);
    }

    return filename;
  }

  StringBuffer _directory;
};

// -----------------------------------------------------------------------------
// --SECTION--                                                        test suite
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief setup
////////////////////////////////////////////////////////////////////////////////

BOOST_FIXTURE_TEST_SUITE(CFilesTest, CFilesSetup)

////////////////////////////////////////////////////////////////////////////////
/// @brief test file exists
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_existsfile) {
  StringBuffer* filename = writeFile("");
  BOOST_CHECK_EQUAL(true, TRI_ExistsFile(filename->c_str()));
  TRI_UnlinkFile(filename->c_str());

  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size empty file
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_empty) {
  StringBuffer* filename = writeFile("");
  BOOST_CHECK_EQUAL(0, (int) TRI_SizeFile(filename->c_str()));

  TRI_UnlinkFile(filename->c_str());
  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_exists) {
  const char* buffer = "the quick brown fox";

  StringBuffer* filename = writeFile(buffer);
  BOOST_CHECK_EQUAL(strlen(buffer), (int) TRI_SizeFile(filename->c_str()));

  TRI_UnlinkFile(filename->c_str());
  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size, non existing file
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_non) {
  BOOST_CHECK_EQUAL((int) -1, (int) TRI_SizeFile("h5uuuuui3unn645wejhdjhikjdsf"));
  BOOST_CHECK_EQUAL((int) -1, (int) TRI_SizeFile("dihnui8ngiu54"));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generate tests
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE_END ()

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:
<commit_msg>fixed uninitialised bytes in call to write<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for files.c
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include <boost/test/unit_test.hpp>

#include "Basics/StringBuffer.h"
#include "BasicsC/files.h"

using namespace triagens::basics;

// -----------------------------------------------------------------------------
// --SECTION--                                                 setup / tear-down
// -----------------------------------------------------------------------------

struct CFilesSetup {
  CFilesSetup () : _directory(TRI_UNKNOWN_MEM_ZONE) {
    BOOST_TEST_MESSAGE("setup files");

    _directory.appendText("/tmp/arangotest-");
    _directory.appendInteger((uint64_t) TRI_microtime());

    TRI_CreateDirectory(_directory.c_str());
  }

  ~CFilesSetup () {
    BOOST_TEST_MESSAGE("tear-down files");

    // let's be sure we delete the right stuff
    assert(_directory.length() > 10);
    assert(memcmp((void*) _directory.c_str(), (void*) "/tmp/arangotest-", 16) == 0);

    TRI_RemoveDirectory(_directory.c_str());
  }

  StringBuffer* writeFile (const char* blob) {
    static uint64_t counter = 0;

    StringBuffer* filename = new StringBuffer(TRI_UNKNOWN_MEM_ZONE);
    filename->appendText(_directory);
    filename->appendText("/tmp-");
    filename->appendInteger(++counter);

    int fd = TRI_OPEN(filename->c_str(), O_RDWR | O_CREAT);

    if (fd) {
      ::write(fd, blob, strlen(blob));
      ::close(fd);
    }
    else {
      BOOST_CHECK_EQUAL(false, true);
    }

    return filename;
  }

  StringBuffer _directory;
};

// -----------------------------------------------------------------------------
// --SECTION--                                                        test suite
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief setup
////////////////////////////////////////////////////////////////////////////////

BOOST_FIXTURE_TEST_SUITE(CFilesTest, CFilesSetup)

////////////////////////////////////////////////////////////////////////////////
/// @brief test file exists
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_existsfile) {
  StringBuffer* filename = writeFile("");
  BOOST_CHECK_EQUAL(true, TRI_ExistsFile(filename->c_str()));
  TRI_UnlinkFile(filename->c_str());

  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size empty file
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_empty) {
  StringBuffer* filename = writeFile("");
  BOOST_CHECK_EQUAL(0, (int) TRI_SizeFile(filename->c_str()));

  TRI_UnlinkFile(filename->c_str());
  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_exists) {
  const char* buffer = "the quick brown fox";

  StringBuffer* filename = writeFile(buffer);
  BOOST_CHECK_EQUAL(strlen(buffer), (int) TRI_SizeFile(filename->c_str()));

  TRI_UnlinkFile(filename->c_str());
  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size, non existing file
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_non) {
  BOOST_CHECK_EQUAL((int) -1, (int) TRI_SizeFile("h5uuuuui3unn645wejhdjhikjdsf"));
  BOOST_CHECK_EQUAL((int) -1, (int) TRI_SizeFile("dihnui8ngiu54"));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generate tests
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE_END ()

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:
<|endoftext|>


<commit_before>/*
 *  _____             ___ ___   |
 * |  _  |___ ___ _ _|_  |_  |  |  C/C++ framework for 32-bit AVRs
 * |     | -_|  _| | |_  |  _|  |
 * |__|__|___|_| |_  |___|___|  |  https://github.com/aery32
 *               |___|          |
 *
 * Copyright (c) 2012, Muiku Oy
 * All rights reserved.
 *
 * LICENSE
 *
 * New BSD License, see the LICENSE.txt bundled with this package. If you did
 * not receive a copy of the license and are unable to obtain it through the
 * world-wide-web, please send an email to contact@muiku.com so we can send
 * you a copy.
 */

#include "aery32/twi.h"

namespace aery {
	volatile avr32_twi_t *twi = &AVR32_TWI;
	volatile uint32_t __twi_lsr = AVR32_TWI.sr;
}

#define TWI_WAS_ACKNOWLEDGED() ((aery::__twi_lsr & AVR32_TWI_SR_NACK_MASK) == 0)
#define TWI_WASNT_ACKNOWLEDGED() ((aery::__twi_lsr & AVR32_TWI_SR_NACK_MASK) == 1)

static void twi_wait_to_complete(void)
{
	while ((aery::__twi_lsr & AVR32_TWI_SR_TXCOMP_MASK) == 0)
		aery::__twi_lsr = aery::twi->sr;
}

void aery::twi_init_master(void)
{
	/* Software reset. */
	aery::twi->CR.swrst = 1;
	while (aery::twi->CR.swrst);

	/* Setup SLK to 400 kHz by default with 50% duty cycle */
	aery::twi_setup_clkwaveform(0x01, 0x3f, 0x3f);
	aery::twi_clear_internal_address();

	/* Disable slave mode and enable as master */
	aery::twi->CR.svdis = 1;
	aery::twi->CR.msen = 1;
}

void aery::twi_init_slave(uint16_t sla)
{
	/* Software reset. */
	aery::twi->CR.swrst = 1;
	while (aery::twi->CR.swrst);

	/* Disable master mode and enable as slave with SLA */
	aery::twi->SMR.sadr = sla;
	aery::twi->CR.msdis = 1;
	aery::twi->CR.sven = 1;
}

int aery::twi_setup_clkwaveform(uint8_t ckdiv, uint8_t cldiv, uint8_t chdiv)
{
	if (ckdiv > 7)
		return -1;
	aery::twi->CWGR.ckdiv = ckdiv;
	aery::twi->CWGR.cldiv = cldiv;
	aery::twi->CWGR.chdiv = chdiv;
	return 0;
}

void aery::twi_select_slave(uint16_t sla)
{
	aery::twi->MMR.dadr = sla;
}

int aery::twi_use_internal_address(uint32_t iadr, uint8_t n)
{
	if (iadr > 0xffffff)
		return -1;
	aery::twi->IADR.iadr = iadr;
	aery::twi->MMR.iadrsz = n;
	return 0;
}

void aery::twi_clear_internal_address(void)
{
	aery::twi_use_internal_address(0, 0);
}

size_t aery::twi_read_nbytes(uint8_t *data, size_t n)
{
	size_t i = 0;

	if (n == 1)
		return aery::twi_read_byte(data);

	/* Switch to read mode */
	aery::twi->MMR.mread = 1;

	/* Start multiple byte read operation */
	aery::twi->cr |= AVR32_TWI_CR_START_MASK;

	for (; i < n - 1; i++) {
		while (aery::twi_isbusy());
		if (TWI_WASNT_ACKNOWLEDGED())
			break;
		data[i] = aery::twi->RHR.rxdata;
	}

	/* Send STOP */
	aery::twi->cr |= AVR32_TWI_CR_STOP_MASK;

	/* Read last byte */
	if (TWI_WAS_ACKNOWLEDGED()) {
		while (aery::twi_isbusy());
		if (TWI_WAS_ACKNOWLEDGED())
			data[i++] = aery::twi->RHR.rxdata;
	}

	twi_wait_to_complete();
	return i;
}

size_t aery::twi_read_nbytes(uint8_t *data, size_t n, uint8_t iadr)
{
	aery::twi_use_internal_address(iadr, 1);
	return aery::twi_read_nbytes(data, n);
}

size_t aery::twi_read_byte(uint8_t *data)
{
	size_t i = 0;

	/* Switch to read mode */
	aery::twi->MMR.mread = 1;

	/* Start one byte read operation */
	aery::twi->cr |= AVR32_TWI_CR_START_MASK | AVR32_TWI_CR_STOP_MASK;

	while (aery::twi_isbusy());
	if (TWI_WAS_ACKNOWLEDGED())
		data[i++] = aery::twi->RHR.rxdata;

	twi_wait_to_complete();
	return i;
}

size_t aery::twi_read_byte(uint8_t *data, uint8_t iadr)
{
	aery::twi_use_internal_address(iadr, 1);
	return aery::twi_read_byte(data);
}

size_t aery::twi_write_nbytes(uint8_t *data, size_t n)
{
	size_t i = 0;

	/* Switch to write mode */
	aery::twi->MMR.mread = 0;

	for (; i < n; i++) {
		aery::twi->THR.txdata = *data;
		while (aery::twi_isbusy());
		if (TWI_WASNT_ACKNOWLEDGED())
			break;
	}

	twi_wait_to_complete();
	return i;
}

size_t aery::twi_write_nbytes(uint8_t *data, size_t n, uint8_t iadr)
{
	aery::twi_use_internal_address(iadr, 1);
	return aery::twi_write_nbytes(data, n);
}

size_t aery::twi_write_byte(uint8_t data)
{
	return aery::twi_write_nbytes(&data, 1);
}

size_t aery::twi_write_byte(uint8_t data, uint8_t iadr)
{
	return aery::twi_write_nbytes(&data, 1, iadr);
}

bool aery::twi_isbusy(void)
{
	aery::__twi_lsr = aery::twi->sr;
	if (aery::twi->MMR.mread == 1) {
		return (aery::__twi_lsr & AVR32_TWI_SR_RXRDY_MASK) == 0;
	}
	return (aery::__twi_lsr & AVR32_TWI_SR_TXRDY_MASK) == 0;
}
<commit_msg>Remove aery::twi_init_slave()<commit_after>/*
 *  _____             ___ ___   |
 * |  _  |___ ___ _ _|_  |_  |  |  C/C++ framework for 32-bit AVRs
 * |     | -_|  _| | |_  |  _|  |
 * |__|__|___|_| |_  |___|___|  |  https://github.com/aery32
 *               |___|          |
 *
 * Copyright (c) 2012, Muiku Oy
 * All rights reserved.
 *
 * LICENSE
 *
 * New BSD License, see the LICENSE.txt bundled with this package. If you did
 * not receive a copy of the license and are unable to obtain it through the
 * world-wide-web, please send an email to contact@muiku.com so we can send
 * you a copy.
 */

#include "aery32/twi.h"

namespace aery {
	volatile avr32_twi_t *twi = &AVR32_TWI;
	volatile uint32_t __twi_lsr = AVR32_TWI.sr;
}

#define TWI_WAS_ACKNOWLEDGED() ((aery::__twi_lsr & AVR32_TWI_SR_NACK_MASK) == 0)
#define TWI_WASNT_ACKNOWLEDGED() ((aery::__twi_lsr & AVR32_TWI_SR_NACK_MASK) == 1)

static void twi_wait_to_complete(void)
{
	while ((aery::__twi_lsr & AVR32_TWI_SR_TXCOMP_MASK) == 0)
		aery::__twi_lsr = aery::twi->sr;
}

void aery::twi_init_master(void)
{
	/* Software reset. */
	aery::twi->CR.swrst = 1;
	while (aery::twi->CR.swrst);

	/* Setup SLK to 400 kHz by default with 50% duty cycle */
	aery::twi_setup_clkwaveform(0x01, 0x3f, 0x3f);
	aery::twi_clear_internal_address();

	/* Disable slave mode and enable as master */
	aery::twi->CR.svdis = 1;
	aery::twi->CR.msen = 1;
}

// void aery::twi_init_slave(uint16_t sla)
// {
// 	/* Software reset. */
// 	aery::twi->CR.swrst = 1;
// 	while (aery::twi->CR.swrst);

// 	 Disable master mode and enable as slave with SLA
// 	aery::twi->SMR.sadr = sla;
// 	aery::twi->CR.msdis = 1;
// 	aery::twi->CR.sven = 1;
// }

int aery::twi_setup_clkwaveform(uint8_t ckdiv, uint8_t cldiv, uint8_t chdiv)
{
	if (ckdiv > 7)
		return -1;
	aery::twi->CWGR.ckdiv = ckdiv;
	aery::twi->CWGR.cldiv = cldiv;
	aery::twi->CWGR.chdiv = chdiv;
	return 0;
}

void aery::twi_select_slave(uint16_t sla)
{
	aery::twi->MMR.dadr = sla;
}

int aery::twi_use_internal_address(uint32_t iadr, uint8_t n)
{
	if (iadr > 0xffffff)
		return -1;
	aery::twi->IADR.iadr = iadr;
	aery::twi->MMR.iadrsz = n;
	return 0;
}

void aery::twi_clear_internal_address(void)
{
	aery::twi_use_internal_address(0, 0);
}

size_t aery::twi_read_nbytes(uint8_t *data, size_t n)
{
	size_t i = 0;

	if (n == 1)
		return aery::twi_read_byte(data);

	/* Switch to read mode */
	aery::twi->MMR.mread = 1;

	/* Start multiple byte read operation */
	aery::twi->cr |= AVR32_TWI_CR_START_MASK;

	for (; i < n - 1; i++) {
		while (aery::twi_isbusy());
		if (TWI_WASNT_ACKNOWLEDGED())
			break;
		data[i] = aery::twi->RHR.rxdata;
	}

	/* Send STOP */
	aery::twi->cr |= AVR32_TWI_CR_STOP_MASK;

	/* Read last byte */
	if (TWI_WAS_ACKNOWLEDGED()) {
		while (aery::twi_isbusy());
		if (TWI_WAS_ACKNOWLEDGED())
			data[i++] = aery::twi->RHR.rxdata;
	}

	twi_wait_to_complete();
	return i;
}

size_t aery::twi_read_nbytes(uint8_t *data, size_t n, uint8_t iadr)
{
	aery::twi_use_internal_address(iadr, 1);
	return aery::twi_read_nbytes(data, n);
}

size_t aery::twi_read_byte(uint8_t *data)
{
	size_t i = 0;

	/* Switch to read mode */
	aery::twi->MMR.mread = 1;

	/* Start one byte read operation */
	aery::twi->cr |= AVR32_TWI_CR_START_MASK | AVR32_TWI_CR_STOP_MASK;

	while (aery::twi_isbusy());
	if (TWI_WAS_ACKNOWLEDGED())
		data[i++] = aery::twi->RHR.rxdata;

	twi_wait_to_complete();
	return i;
}

size_t aery::twi_read_byte(uint8_t *data, uint8_t iadr)
{
	aery::twi_use_internal_address(iadr, 1);
	return aery::twi_read_byte(data);
}

size_t aery::twi_write_nbytes(uint8_t *data, size_t n)
{
	size_t i = 0;

	/* Switch to write mode */
	aery::twi->MMR.mread = 0;

	for (; i < n; i++) {
		aery::twi->THR.txdata = *data;
		while (aery::twi_isbusy());
		if (TWI_WASNT_ACKNOWLEDGED())
			break;
	}

	twi_wait_to_complete();
	return i;
}

size_t aery::twi_write_nbytes(uint8_t *data, size_t n, uint8_t iadr)
{
	aery::twi_use_internal_address(iadr, 1);
	return aery::twi_write_nbytes(data, n);
}

size_t aery::twi_write_byte(uint8_t data)
{
	return aery::twi_write_nbytes(&data, 1);
}

size_t aery::twi_write_byte(uint8_t data, uint8_t iadr)
{
	return aery::twi_write_nbytes(&data, 1, iadr);
}

bool aery::twi_isbusy(void)
{
	aery::__twi_lsr = aery::twi->sr;
	if (aery::twi->MMR.mread == 1) {
		return (aery::__twi_lsr & AVR32_TWI_SR_RXRDY_MASK) == 0;
	}
	return (aery::__twi_lsr & AVR32_TWI_SR_TXRDY_MASK) == 0;
}
<|endoftext|>


<commit_before>#ifndef MP_LINKEDLIST_HPP
#define MP_LINKEDLIST_HPP

#include <boost/shared_ptr.hpp>

// lockfree

template<typename T>
class LinkedList {
public:
	struct Item;
	typedef boost::shared_ptr<Item> ItemPtr;
	struct Item {
		ItemPtr next;
		T value;
	};

private:
	ItemPtr first, last;

public:
	// not thread-safe!
	struct Iterator {
		ItemPtr ptr;

		Iterator(const ItemPtr& _ptr) : ptr(_ptr) {}

		T& operator*() {
			return ptr->value;
		}

		Iterator& operator++() {
			ptr = ptr->next;
			return *this;
		}

		bool operator!=(const Iterator& other) const {
			return ptr != other.ptr;
		}
	};

	Iterator begin() {
		return Iterator(first);
	}

	Iterator end() {
		return Iterator(NULL);
	}

	// only single producer supported
	void push_back() {
		ItemPtr item(new Item());
		ItemPtr oldLast = last;
		if(!first) first = item;
		if(!last) last = item;
		else {
			last->next = item;
			last = item;
		}
	}

	// only single consumer supported
	ItemPtr pop_front() {
		if(first) {
			ItemPtr oldFirst = first;
			first = first->next;
			if(!first) last = NULL;
			return oldFirst;
		}
		return NULL;
	}

	// not multithreading safe at all
	void clear() {
		first.reset();
		last.reset();
	}

	bool empty() {
		return first == NULL;
	}

	// be very careful!
	T& front() { return first->value; }
	T& back() { return last->value; }

};

#endif // LINKEDLIST_HPP
<commit_msg>cleanup<commit_after>#ifndef MP_LINKEDLIST_HPP
#define MP_LINKEDLIST_HPP

#include <boost/shared_ptr.hpp>

// lockfree

template<typename T>
class LinkedList {
public:
	struct Item;
	typedef boost::shared_ptr<Item> ItemPtr;
	struct Item {
		ItemPtr next;
		T value;
	};

private:
	ItemPtr first, last;

public:
	// not thread-safe!
	struct Iterator {
		ItemPtr ptr;

		Iterator(const ItemPtr& _ptr) : ptr(_ptr) {}

		T& operator*() {
			return ptr->value;
		}

		Iterator& operator++() {
			ptr = ptr->next;
			return *this;
		}

		bool operator!=(const Iterator& other) const {
			return ptr != other.ptr;
		}
	};

	Iterator begin() {
		return Iterator(first);
	}

	Iterator end() {
		return Iterator(NULL);
	}

	// only single producer supported
	void push_back() {
		ItemPtr item(new Item());
		if(!first) first = item;
		if(!last) last = item;
		else {
			last->next = item;
			last = item;
		}
	}

	// only single consumer supported
	ItemPtr pop_front() {
		if(first) {
			ItemPtr oldFirst = first;
			first = first->next;
			if(!first) last = NULL;
			return oldFirst;
		}
		return NULL;
	}

	// not multithreading safe at all
	void clear() {
		first.reset();
		last.reset();
	}

	bool empty() {
		return first == NULL;
	}

	// be very careful!
	T& front() { return first->value; }
	T& back() { return last->value; }

};

#endif // LINKEDLIST_HPP
<|endoftext|>


<commit_before>/**
 *   C++ Examples - a collection of C++ examples intended to serve as a tutorial
 *   Copyright (C) 2011 Alejandro Cabrera
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **/
#include <iostream>
#include <memory>
#include <algorithm>
#include <iterator>
#include <initializer_list>
using namespace std;

template <typename T>
struct Sequence {
	typedef T value_type;
	typedef T& reference;
	typedef const T& const_reference;
	typedef T* iterator;
	typedef const T*const const_iterator;
	typedef size_t size_type;

	Sequence() : size(0), data(nullptr) {}
	explicit Sequence(const size_type n)
		: size(n) {
		data = new T[n];
	}

	Sequence(const size_type n, const T init)
		: size(n) {
		data = new T[n];
		for (size_t i = 0; i < n; ++i)
			data[i] = init;
	}

	Sequence(const initializer_list<value_type>& ilist)
		: size(ilist.size())
	{
		data = new T[this->size];
		copy(ilist.begin(), ilist.end(), data);
	}

	iterator begin()
	{
		return data;
	}

	iterator end()
	{
		return data + size;
	}

private:
	size_type size;
	T* data;
};

int main()
{
	// already supported by C++98
	int arr[] = {1,2,3,4,5};

	// support added in C++11
	vector<int> x = {1,2,3,4,5};

	// our version using C++11
	Sequence<int> s = {1,2,3,4,5};

	cout << "array [";
	copy(arr, arr+5, ostream_iterator<int>(cout, ","));
	cout << "]\n";

	cout << "vector [";
	copy(begin(x), end(x), ostream_iterator<int>(cout, ","));
	cout << "]\n";

	cout << "sequence [";
	copy(begin(s), end(s), ostream_iterator<int>(cout, ","));
	cout << "]\n";

	return 0;
}
<commit_msg>Fixed output error in ilist.cpp.<commit_after>/**
 *   C++ Examples - a collection of C++ examples intended to serve as a tutorial
 *   Copyright (C) 2011 Alejandro Cabrera
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **/
#include <iostream>
#include <memory>
#include <algorithm>
#include <iterator>
#include <initializer_list>
using namespace std;

template <typename T>
struct Sequence {
	typedef T value_type;
	typedef T& reference;
	typedef const T& const_reference;
	typedef T* iterator;
	typedef const T*const const_iterator;
	typedef size_t size_type;

	Sequence() : size(0), data(nullptr) {}
	explicit Sequence(const size_type n)
		: size(n) {
		data = new T[n];
	}

	Sequence(const size_type n, const T init)
		: size(n) {
		data = new T[n];
		for (size_t i = 0; i < n; ++i)
			data[i] = init;
	}

	Sequence(const initializer_list<value_type>& ilist)
		: size(ilist.size())
	{
		data = new T[this->size];
		copy(ilist.begin(), ilist.end(), data);
	}

	iterator begin()
	{
		return data;
	}

	iterator end()
	{
		return data + size;
	}

private:
	size_type size;
	T* data;
};

int main()
{
	// already supported by C++98
	int arr[] = {1,2,3,4,5};

	// support added in C++11
	vector<int> x = {1,2,3,4,5};

	// our version using C++11
	Sequence<int> s = {1,2,3,4,5};

	cout << "array [";
	copy(arr, arr+5, ostream_iterator<int>(cout, " "));
	cout << "]\n";

	cout << "vector [";
	copy(begin(x), end(x), ostream_iterator<int>(cout, " "));
	cout << "]\n";

	cout << "sequence [";
	copy(begin(s), end(s), ostream_iterator<int>(cout, " "));
	cout << "]\n";

	return 0;
}
<|endoftext|>


<commit_before>#include "Raytrace.h"
#include "VectorMath.h"

using namespace std;

queue<Camera*> cameraQ;
queue<SceneObject*> objectQ;

const double aspect = (double)H/(double)W;
double zmaxG = 1000;

int cameraNum = 0;
int iterations = 0;

EntityID lastProc = NONE;

int main(int argc, char * argv[])
{
	bool manualFilename = false; //If true, use a predefined scene file
	string fn; //name of file
	if(manualFilename)
		fn = "K:\\git\\Naive-Raytracer\\scenes";

	if(argc != 2 && !manualFilename)
		cout << "Incorrect argument amount. Program terminating.\n";
	else if(argc == 2 && !manualFilename)
		fn = argv[1];

	//Read input from file
	if(processInput(fn) == 0) return 0;

    BMP image;
    image.SetSize(W,H);
    image.SetBitDepth(32);
	for(int i = 0; cameraQ.size() > 0; i++)
	{
		cameraNum = i;
		Camera* c = cameraQ.front();
		zmaxG = c->zmax;
		for(int y = 0; y < H; y++)
		{
			for(int x = 0; x < W; x++)
			{
				double height = c->width * aspect; //Height of image plane
				double width = c->width; //Width of image plane
				bool isPerspective = c->perspective; //False if orthogonal, true if perspective

				double uc = -1*width/2 + width/2 * 2*x/W;
				double vr = -1*height/2 + height/2 * 2*y/H;

				norm(c->direction);
				norm(c->up);

				Vector vLeft = cross3(c->direction,c->up);

				//Point on image plane
				Point pPointOnImagePlane = c->origin + c->zmin * c->direction + uc * vLeft + vr * c->up;

				Vector vCamToImagePlane; //Vector from the camera to the image plane

				if(isPerspective) //If camera is perspective
				{
					vCamToImagePlane = pPointOnImagePlane - c->origin;
				}
				else //If camera is orthogonal
				{
					vCamToImagePlane = c->direction;
				}
				//vCamToImagePlane = c->direction;

				Ray* r = new Ray(); //Ray from the camera to the image plane
				r->dir = vCamToImagePlane;

				if(isPerspective)
					r->start = c->origin;
				else
					r->start = pPointOnImagePlane;

				bool lightT = false;

				if(x == 134 && y == 56) {
					int z = 5;
				}
				Color col = raytrace(r,lightT);
				if(DIAGNOSTIC_STATUS == IS_LIT) col.adjustColorForDiagnosticIsLit();

				if(c->grayscale) {
					double grayscaleVal = col.r * 0.3 + col.g * 0.59 + col.b * 0.11;
					image(W-x-1,H-y-1)->Red   = (unsigned char)grayscaleVal;
					image(W-x-1,H-y-1)->Green = (unsigned char)grayscaleVal;
					image(W-x-1,H-y-1)->Blue  = (unsigned char)grayscaleVal;
				}
				else {
					image(W-x-1,H-y-1)->Red   = (unsigned char)col.r;
					image(W-x-1,H-y-1)->Green = (unsigned char)col.g;
					image(W-x-1,H-y-1)->Blue  = (unsigned char)col.b;
				}
			    image(W-x-1,H-y-1)->Alpha = 0;

				delete r;
			}
		}

		string sceneName = fn.substr(0,fn.length()-4);
		char temp[33];
		_itoa_s(i,temp,10);
		sceneName += "-";
		sceneName += temp;
		sceneName += ".bmp";

		string sceneName_aa = sceneName.substr(0,sceneName.length()-4)+"_aa_naive.bmp";
		if(DIAGNOSTIC_STATUS == NORMAL) generateAABMP(image).WriteToFile(sceneName_aa.c_str());

		image.WriteToFile(sceneName.c_str());
		cameraQ.pop();
	}

    BMP texture;
    return 0;
}

Color raytrace(Ray* r, bool &light)
{
	Color c = Color::ColorBlack();

	//find nearest intersection
	SceneObject* closestO = NULL;
	Point oInt;

	closestO = findClosestObject(r, oInt);
	if(DIAGNOSTIC_STATUS == IS_HIT) {
		if(closestO) return Color::ColorWhite();
		else return Color::ColorBlack();
	}

	double oDist;
	if(closestO)	oDist = dist3Compare(oInt,r->start);
	else			oDist = numeric_limits<double>::max();

	//If >=1 entity found
	if(oDist != numeric_limits<double>::max())
	{
		if(!closestO->isLight && !light) //if not a light
		{
			Color materialTexture;
			Color llocal = Color::ColorBlack();
			Color reflect = Color::ColorBlack();
			Color refract = Color::ColorBlack();

			Vector normal = closestO->calculateNormalForPoint(oInt,r->start);
			norm(normal);

			llocal = calculateLocalLighting(oInt,normal,closestO->objectType);
			iterations++;
			if(closestO->getReflection() != 0 && iterations < 5) reflect = calculateReflectedRay(*r,oInt,normal,closestO->objectType);
			if(closestO->getRefraction() != 0 && iterations < 5) refract = calculateRefractedRay(*r,oInt,normal,closestO->objectType);
			iterations--;
			if(closestO->hasTexture) materialTexture = closestO->calculateTextureFromMaterial(oInt);

			if(closestO->hasTexture)
			{
				if(DIAGNOSTIC_STATUS == TEXTURE_MAPPING) {
					c.r = materialTexture.r * 255;
					c.g = materialTexture.g * 255;
					c.b = materialTexture.b * 255;
					return c;
				}
				c.r = llocal.r * materialTexture.r * 255 + closestO->getReflection() * reflect.r + closestO->getRefraction() * refract.r;
				c.g = llocal.g * materialTexture.g * 255 + closestO->getReflection() * reflect.g + closestO->getRefraction() * refract.g;
				c.b = llocal.b * materialTexture.b * 255 + closestO->getReflection() * reflect.b + closestO->getRefraction() * refract.b;
			}
			else
			{
				c.r = llocal.r * closestO->getColor().r * 255 + closestO->getReflection() * reflect.r + closestO->getRefraction() * refract.r;
				c.g = llocal.g * closestO->getColor().g * 255 + closestO->getReflection() * reflect.g + closestO->getRefraction() * refract.g;
				c.b = llocal.b * closestO->getColor().b * 255 + closestO->getReflection() * reflect.b + closestO->getRefraction() * refract.b;
			}
			light = false;
		}
		else if (closestO->isLight) //Light is closest
		{
			c.r = closestO->getColor().r * 255;
			c.g = closestO->getColor().g * 255;
			c.b = closestO->getColor().b * 255;

			light = true;
		}
		else light = false;
	}

	return c;
}

Color calculateLocalLighting(Point intercept, Vector normal, EntityID id) {
	Color llocal = Color::ColorBlack();
	for(unsigned int i = 0; i < objectQ.size(); i++)
	{
		SceneObject* l = objectQ.front();
		objectQ.pop();
		objectQ.push(l);
		if(!l->isLight) continue;

		Ray* lightRay = new Ray();
		bool lig = true;

		//Start of the ray (moved a bit so we won't intercept the object)
		Point lStart = intercept + 0.000001 * (l->origin - intercept);

		//Direction from the object *to* the light source
		Vector lDir = l->origin - lStart;

		lightRay->dir = lDir;
		lightRay->start = lStart;

		lastProc = id;
		Color receivedColor = raytrace(lightRay,lig);
		lastProc = NONE;

		if(lig) //We see the light from the point
		{
			//Direction from the light source to the plane.  Used for calculating lambert
			Vector lToObject = lDir;

			norm(lToObject);

			receivedColor.r /= 255.f;
			receivedColor.g /= 255.f;
			receivedColor.b /= 255.f;

			double lightSourceIntensity = cosAngle(lToObject,normal);
			if(lightSourceIntensity < 0) lightSourceIntensity = 0;
			llocal.r += receivedColor.r * lightSourceIntensity;
			llocal.g += receivedColor.g * lightSourceIntensity;
			llocal.b += receivedColor.b * lightSourceIntensity;
			if(llocal.r > 1) llocal.r = 1;
			if(llocal.g > 1) llocal.g = 1;
			if(llocal.b > 1) llocal.b = 1;
		}
		delete lightRay;
	}
	return llocal;
}

//Calc reflected vector
Color calculateReflectedRay(Ray r, Point intercept, Vector normal, EntityID id) {
	double angle = dot3(normal,r.dir);
	Vector reflectVec = -2 * angle * normal + r.dir;

	//Generate reflected ray
	Ray reflectRay;
	reflectRay.dir = reflectVec;
	reflectRay.start = intercept + 0.000001 * reflectVec;

	bool lig = false;
	lastProc = id;
	return raytrace(&reflectRay,lig);
	lastProc = NONE;
}

//Calc refracted vector
Color calculateRefractedRay(Ray r, Point intercept, Vector normal, EntityID id) {
	Ray refractRay;
	refractRay.dir = r.dir;
	refractRay.start = intercept + 0.000001 * r.dir;

	bool lig = false;
	lastProc = id;
	return raytrace(&refractRay,lig);
	lastProc = NONE;
}

SceneObject *findClosestObject(Ray *r, Point &intersect) {
	SceneObject *closestObject = NULL;
	for(unsigned int i = 0; i < objectQ.size(); i++) //look for closest object
	{
		SceneObject* tempO = objectQ.front();
		objectQ.pop();
		objectQ.push(tempO);

		Point objectIntersect;
		if(tempO->intersect(r,objectIntersect)) {
			if(!closestObject) //If no previous object intersections found
			{
				closestObject = tempO;
				intersect = objectIntersect;
			}
			else if(dist3Compare(objectIntersect, r->start) < dist3Compare(intersect, r->start)) //If closer than previous
			{
				closestObject = tempO;
				intersect = objectIntersect;
			}
		}
	}

	return closestObject;
}

int processInput(string filename)
{
	ifstream sceneFile;
	string line; //We will be temporarily storing input here

	sceneFile.open(filename.c_str()); //Open file

	if(!sceneFile.is_open())
	{
		cout << "Scene file failed to open.\n";
		return 0;
	}
	while(!sceneFile.eof()) //Loop through all input
	{
		getline(sceneFile,line);

		queue<string> lineContents;
		explode(line," ",&lineContents);

		if(lineContents.size() == 0) continue;
		string word = lineContents.front();
		lineContents.pop();

		if(word[0] == '#' || line[0] == '\n' || line[0] == '\r') continue;

		if(word == "camera")
		{
			Camera* c = new Camera(sceneFile);
			cameraQ.push(c);
		}
		else if(word == "plane")
		{
			Plane* p = new Plane(sceneFile);
			objectQ.push(p);
		}
		else if(word == "sphere")
		{
			Sphere* s = new Sphere(sceneFile);
			objectQ.push(s);
		}
		else if(word == "light")
		{
			Light* l = new Light(sceneFile);
			objectQ.push(l);
		}
		else
		{
			cout << "Incorrect syntax in line \n\"" << line << "\"." << endl;
			return 0;
		}
	}
	return 1;
}<commit_msg>Reflection and transparency both work - increasing either value will decrease the impact of the diffuse lighting.<commit_after>#include "Raytrace.h"
#include "VectorMath.h"

using namespace std;

queue<Camera*> cameraQ;
queue<SceneObject*> objectQ;

const double aspect = (double)H/(double)W;
double zmaxG = 1000;

int cameraNum = 0;
int iterations = 0;

EntityID lastProc = NONE;

int main(int argc, char * argv[])
{
	bool manualFilename = false; //If true, use a predefined scene file
	string fn; //name of file
	if(manualFilename)
		fn = "K:\\git\\Naive-Raytracer\\scenes";

	if(argc != 2 && !manualFilename)
		cout << "Incorrect argument amount. Program terminating.\n";
	else if(argc == 2 && !manualFilename)
		fn = argv[1];

	//Read input from file
	if(processInput(fn) == 0) return 0;

    BMP image;
    image.SetSize(W,H);
    image.SetBitDepth(32);
	for(int i = 0; cameraQ.size() > 0; i++)
	{
		cameraNum = i;
		Camera* c = cameraQ.front();
		zmaxG = c->zmax;
		for(int y = 0; y < H; y++)
		{
			for(int x = 0; x < W; x++)
			{
				double height = c->width * aspect; //Height of image plane
				double width = c->width; //Width of image plane
				bool isPerspective = c->perspective; //False if orthogonal, true if perspective

				double uc = -1*width/2 + width/2 * 2*x/W;
				double vr = -1*height/2 + height/2 * 2*y/H;

				norm(c->direction);
				norm(c->up);

				Vector vLeft = cross3(c->direction,c->up);

				//Point on image plane
				Point pPointOnImagePlane = c->origin + c->zmin * c->direction + uc * vLeft + vr * c->up;

				Vector vCamToImagePlane; //Vector from the camera to the image plane

				if(isPerspective) //If camera is perspective
				{
					vCamToImagePlane = pPointOnImagePlane - c->origin;
				}
				else //If camera is orthogonal
				{
					vCamToImagePlane = c->direction;
				}
				//vCamToImagePlane = c->direction;

				Ray* r = new Ray(); //Ray from the camera to the image plane
				r->dir = vCamToImagePlane;

				if(isPerspective)
					r->start = c->origin;
				else
					r->start = pPointOnImagePlane;

				bool lightT = false;

				if(x == 134 && y == 56) {
					int z = 5;
				}
				Color col = raytrace(r,lightT);
				if(DIAGNOSTIC_STATUS == IS_LIT) col.adjustColorForDiagnosticIsLit();

				if(c->grayscale) {
					double grayscaleVal = col.r * 0.3 + col.g * 0.59 + col.b * 0.11;
					image(W-x-1,H-y-1)->Red   = (unsigned char)grayscaleVal;
					image(W-x-1,H-y-1)->Green = (unsigned char)grayscaleVal;
					image(W-x-1,H-y-1)->Blue  = (unsigned char)grayscaleVal;
				}
				else {
					image(W-x-1,H-y-1)->Red   = (unsigned char)col.r;
					image(W-x-1,H-y-1)->Green = (unsigned char)col.g;
					image(W-x-1,H-y-1)->Blue  = (unsigned char)col.b;
				}
			    image(W-x-1,H-y-1)->Alpha = 0;

				delete r;
			}
		}

		string sceneName = fn.substr(0,fn.length()-4);
		char temp[33];
		_itoa_s(i,temp,10);
		sceneName += "-";
		sceneName += temp;
		sceneName += ".bmp";

		string sceneName_aa = sceneName.substr(0,sceneName.length()-4)+"_aa_naive.bmp";
		if(DIAGNOSTIC_STATUS == NORMAL) generateAABMP(image).WriteToFile(sceneName_aa.c_str());

		image.WriteToFile(sceneName.c_str());
		cameraQ.pop();
	}

    BMP texture;
    return 0;
}

Color raytrace(Ray* r, bool &light)
{
	Color c = Color::ColorBlack();

	//find nearest intersection
	SceneObject* closestO = NULL;
	Point oInt;

	closestO = findClosestObject(r, oInt);
	if(DIAGNOSTIC_STATUS == IS_HIT) {
		if(closestO) return Color::ColorWhite();
		else return Color::ColorBlack();
	}

	double oDist;
	if(closestO)	oDist = dist3Compare(oInt,r->start);
	else			oDist = numeric_limits<double>::max();

	//If >=1 entity found
	if(oDist != numeric_limits<double>::max())
	{
		if(!closestO->isLight && !light) //if not a light
		{
			Color materialTexture;
			Color llocal = Color::ColorBlack();
			Color reflect = Color::ColorBlack();
			Color refract = Color::ColorBlack();

			Vector normal = closestO->calculateNormalForPoint(oInt,r->start);
			norm(normal);

			llocal = calculateLocalLighting(oInt,normal,closestO->objectType);
			iterations++;
			if(closestO->getReflection() != 0 && iterations < 5) reflect = calculateReflectedRay(*r,oInt,normal,closestO->objectType);
			if(closestO->getRefraction() != 0 && iterations < 5) refract = calculateRefractedRay(*r,oInt,normal,closestO->objectType);
			iterations--;
			if(closestO->hasTexture) materialTexture = closestO->calculateTextureFromMaterial(oInt);

			double percentDiffuse = 1.f - closestO->getReflection() - closestO->getRefraction();
			if(percentDiffuse < 0) percentDiffuse = 0;

			if(closestO->hasTexture)
			{
				if(DIAGNOSTIC_STATUS == TEXTURE_MAPPING) {
					c.r = materialTexture.r * 255;
					c.g = materialTexture.g * 255;
					c.b = materialTexture.b * 255;
					return c;
				}
				c.r = llocal.r * materialTexture.r * 255 * percentDiffuse + closestO->getReflection() * reflect.r + closestO->getRefraction() * refract.r;
				c.g = llocal.g * materialTexture.g * 255 * percentDiffuse + closestO->getReflection() * reflect.g + closestO->getRefraction() * refract.g;
				c.b = llocal.b * materialTexture.b * 255 * percentDiffuse + closestO->getReflection() * reflect.b + closestO->getRefraction() * refract.b;
			}
			else
			{
				c.r = llocal.r * closestO->getColor().r * 255 * percentDiffuse + closestO->getReflection() * reflect.r + closestO->getRefraction() * refract.r;
				c.g = llocal.g * closestO->getColor().g * 255 * percentDiffuse + closestO->getReflection() * reflect.g + closestO->getRefraction() * refract.g;
				c.b = llocal.b * closestO->getColor().b * 255 * percentDiffuse + closestO->getReflection() * reflect.b + closestO->getRefraction() * refract.b;
			}
			light = false;
		}
		else if (closestO->isLight) //Light is closest
		{
			c.r = closestO->getColor().r * 255;
			c.g = closestO->getColor().g * 255;
			c.b = closestO->getColor().b * 255;

			light = true;
		}
		else light = false;
	}

	return c;
}

Color calculateLocalLighting(Point intercept, Vector normal, EntityID id) {
	Color llocal = Color::ColorBlack();
	for(unsigned int i = 0; i < objectQ.size(); i++)
	{
		SceneObject* l = objectQ.front();
		objectQ.pop();
		objectQ.push(l);
		if(!l->isLight) continue;

		Ray* lightRay = new Ray();
		bool lig = true;

		//Start of the ray (moved a bit so we won't intercept the object)
		Point lStart = intercept + 0.000001 * (l->origin - intercept);

		//Direction from the object *to* the light source
		Vector lDir = l->origin - lStart;

		lightRay->dir = lDir;
		lightRay->start = lStart;

		lastProc = id;
		Color receivedColor = raytrace(lightRay,lig);
		lastProc = NONE;

		if(lig) //We see the light from the point
		{
			//Direction from the light source to the plane.  Used for calculating lambert
			Vector lToObject = lDir;

			norm(lToObject);

			receivedColor.r /= 255.f;
			receivedColor.g /= 255.f;
			receivedColor.b /= 255.f;

			double lightSourceIntensity = cosAngle(lToObject,normal);
			if(lightSourceIntensity < 0) lightSourceIntensity = 0;
			llocal.r += receivedColor.r * lightSourceIntensity;
			llocal.g += receivedColor.g * lightSourceIntensity;
			llocal.b += receivedColor.b * lightSourceIntensity;
			if(llocal.r > 1) llocal.r = 1;
			if(llocal.g > 1) llocal.g = 1;
			if(llocal.b > 1) llocal.b = 1;
		}
		delete lightRay;
	}
	return llocal;
}

//Calc reflected vector
Color calculateReflectedRay(Ray r, Point intercept, Vector normal, EntityID id) {
	double angle = dot3(normal,r.dir);
	Vector reflectVec = -2 * angle * normal + r.dir;

	//Generate reflected ray
	Ray reflectRay;
	reflectRay.dir = reflectVec;
	reflectRay.start = intercept + 0.000001 * reflectVec;

	bool lig = false;
	lastProc = id;
	return raytrace(&reflectRay,lig);
	lastProc = NONE;
}

//Calc refracted vector
Color calculateRefractedRay(Ray r, Point intercept, Vector normal, EntityID id) {
	Ray refractRay;
	refractRay.dir = r.dir;
	refractRay.start = intercept + 0.000001 * r.dir;

	bool lig = false;
	lastProc = id;
	return raytrace(&refractRay,lig);
	lastProc = NONE;
}

SceneObject *findClosestObject(Ray *r, Point &intersect) {
	SceneObject *closestObject = NULL;
	for(unsigned int i = 0; i < objectQ.size(); i++) //look for closest object
	{
		SceneObject* tempO = objectQ.front();
		objectQ.pop();
		objectQ.push(tempO);

		Point objectIntersect;
		if(tempO->intersect(r,objectIntersect)) {
			if(!closestObject) //If no previous object intersections found
			{
				closestObject = tempO;
				intersect = objectIntersect;
			}
			else if(dist3Compare(objectIntersect, r->start) < dist3Compare(intersect, r->start)) //If closer than previous
			{
				closestObject = tempO;
				intersect = objectIntersect;
			}
		}
	}

	return closestObject;
}

int processInput(string filename)
{
	ifstream sceneFile;
	string line; //We will be temporarily storing input here

	sceneFile.open(filename.c_str()); //Open file

	if(!sceneFile.is_open())
	{
		cout << "Scene file failed to open.\n";
		return 0;
	}
	while(!sceneFile.eof()) //Loop through all input
	{
		getline(sceneFile,line);

		queue<string> lineContents;
		explode(line," ",&lineContents);

		if(lineContents.size() == 0) continue;
		string word = lineContents.front();
		lineContents.pop();

		if(word[0] == '#' || line[0] == '\n' || line[0] == '\r') continue;

		if(word == "camera")
		{
			Camera* c = new Camera(sceneFile);
			cameraQ.push(c);
		}
		else if(word == "plane")
		{
			Plane* p = new Plane(sceneFile);
			objectQ.push(p);
		}
		else if(word == "sphere")
		{
			Sphere* s = new Sphere(sceneFile);
			objectQ.push(s);
		}
		else if(word == "light")
		{
			Light* l = new Light(sceneFile);
			objectQ.push(l);
		}
		else
		{
			cout << "Incorrect syntax in line \n\"" << line << "\"." << endl;
			return 0;
		}
	}
	return 1;
}<|endoftext|>


<commit_before>/**
 * Author: derselbst
 * Description: provides functions that are used by the worker processes to check whether a bruteforced string generated by the master process matches pwdHash
 */

#include <iostream>
#include <cstring> // std::memcmp()
#include <string>
#include <iomanip>
#include <openssl/sha.h>
#include <byteswap.h>
#include <mpi.h>

using namespace std;

#include "worker.h"
#include "master.h"
#include "alphabet.h"

// contains the hash of the unknown password
char pwdHash[SHA256_DIGEST_LENGTH];

// contains the hash of a bruteforced string
char bruteHash[SHA256_DIGEST_LENGTH];

/**
 * @brief prints 32 bytes of memory
 *
 * prints a hex dump of 32 bytes of memory pointed to
 *
 * @param[in]   pbuf: pointer to some memory, usually containing an SHA256 hash
 */
void printSHAHash(const unsigned int *const pbuf)
{
    // byteswap the integer pointed to, to display hex dump in correct order
    // TODO: how to deal with big endian machines
    cout << hex << uppercase << setw(8) << setfill('0')
         << bswap_32(*(pbuf))
         << bswap_32(*(pbuf+1))
         << bswap_32(*(pbuf+2))
         << bswap_32(*(pbuf+3))
         << bswap_32(*(pbuf+4))
         << bswap_32(*(pbuf+5))
         << bswap_32(*(pbuf+6))
         << bswap_32(*(pbuf+7))
         << endl;
}

/**
 * @brief generates an SHA256 hash
 *
 * generates an SHA256 hash using openSSL
 *
 * @param[in]      input:   a const pointer to const block of data, usually a char array of which the hash is being generated
 * @param[in]      length:  the number of bytes the that input points to holds
 * @param[in,out]  hashStr: const pointer to an array of SHA256_DIGEST_LENGTH bytes that will receive the hash
 *
 * @return returns true if the hash has been generated successfully; returns false if input or hashStr is NULL or length==0; else: false
 */
bool generateSHA256(const void *const input, const size_t &length, char *const hashStr)
{
    if(!hashStr || !input || length==0)
    {
        return false;
    }

    SHA256_CTX hash;
    if(!SHA256_Init(&hash))
    {
        return false;
    }

    if(!SHA256_Update(&hash, input, length))
    {
        return false;
    }

    if(!SHA256_Final(reinterpret_cast<unsigned char*>(hashStr), &hash))
    {
        return false;
    }

    return true;
}

/**
 * @brief checks equality of two hashes
 *
 * calculates the SHA256 hash of 'password' and compares it
 * with the initial password hash
 *
 * @param[in]   password: a const string containing a guessed password
 *
 * @return returns true if hashes match; false if generation of hash failed or hashes not match
 */
bool checkPassword(const string &password)
{
#ifdef VERBOSE
    cout << "checking " << password << endl;
#endif // VERBOSE

    // generate sha hash from entered string and write it to pwdHash
    if(!generateSHA256(password.c_str(), password.length(), bruteHash))
    {
        cerr << "Error when generating SHA256 from \"" << password << "\"" << endl;
        return false;
    }

    if (!memcmp(bruteHash, pwdHash, SHA256_DIGEST_LENGTH))
    {
        cout << "match [" << password << "]" << endl << "hash: " << endl;
        printSHAHash((unsigned int*)bruteHash);
        return true;
    }

    return false;
}

/**
 * @brief the main loop for a worker process
 *
 * continuously looks for incoming strings, generates the SHA
 * hash of it and checks if it matches the secret hash
 */
void worker()
{
    char buf[MaxChars];
    MPI_Status state;

    while(true)
    {
        // check for new msg
        MPI_Probe(MasterProcess, MPI_ANY_TAG, MPI_COMM_WORLD, &state);

        int len;
        // now check status to determine how many bytes were actually received
        MPI_Get_count(&state, MPI_BYTE, &len);

        // receive len bytes
        MPI_Recv(buf, len, MPI_BYTE, MasterProcess, MPI_ANY_TAG, MPI_COMM_WORLD, &state);

        string baseStr(buf, len);

        for(int i=0; i<SizeAlphabet; i++)
        {
            if(checkPassword(baseStr+alphabet[i]))
            {
                //success, tell master
                //MPI_Send(const_cast<char*>(baseStr+alphabet[i].c_str()), baseStr+alphabet[i].length(), MPI_CHAR, MasterProcess, success, MPI_COMM_WORLD);
                cout << "Password found: " << baseStr+alphabet[i] << endl;
                MPI_Abort(MPI_COMM_WORLD, 0);

                break;
            }
        }
    }
}
<commit_msg>corrected reinterpret_cast<commit_after>/**
 * Author: derselbst
 * Description: provides functions that are used by the worker processes to check whether a bruteforced string generated by the master process matches pwdHash
 */

#include <iostream>
#include <cstring> // std::memcmp()
#include <string>
#include <iomanip>
#include <openssl/sha.h>
#include <byteswap.h>
#include <mpi.h>

using namespace std;

#include "worker.h"
#include "master.h"
#include "alphabet.h"

// contains the hash of the unknown password
char pwdHash[SHA256_DIGEST_LENGTH];

// contains the hash of a bruteforced string
char bruteHash[SHA256_DIGEST_LENGTH];

/**
 * @brief prints 32 bytes of memory
 *
 * prints a hex dump of 32 bytes of memory pointed to
 *
 * @param[in]   pbuf: pointer to some memory, usually containing an SHA256 hash
 */
void printSHAHash(const unsigned int *const pbuf)
{
    // byteswap the integer pointed to, to display hex dump in correct order
    // TODO: how to deal with big endian machines
    cout << hex << uppercase << setw(8) << setfill('0')
         << bswap_32(*(pbuf))
         << bswap_32(*(pbuf+1))
         << bswap_32(*(pbuf+2))
         << bswap_32(*(pbuf+3))
         << bswap_32(*(pbuf+4))
         << bswap_32(*(pbuf+5))
         << bswap_32(*(pbuf+6))
         << bswap_32(*(pbuf+7))
         << endl;
}

/**
 * @brief generates an SHA256 hash
 *
 * generates an SHA256 hash using openSSL
 *
 * @param[in]      input:   a const pointer to const block of data, usually a char array of which the hash is being generated
 * @param[in]      length:  the number of bytes the that input points to holds
 * @param[in,out]  hashStr: const pointer to an array of SHA256_DIGEST_LENGTH bytes that will receive the hash
 *
 * @return returns true if the hash has been generated successfully; returns false if input or hashStr is NULL or length==0; else: false
 */
bool generateSHA256(const void *const input, const size_t &length, char *const hashStr)
{
    if(!hashStr || !input || length==0)
    {
        return false;
    }

    SHA256_CTX hash;
    if(!SHA256_Init(&hash))
    {
        return false;
    }

    if(!SHA256_Update(&hash, input, length))
    {
        return false;
    }

    if(!SHA256_Final(reinterpret_cast<unsigned char *const>(hashStr), &hash))
    {
        return false;
    }

    return true;
}

/**
 * @brief checks equality of two hashes
 *
 * calculates the SHA256 hash of 'password' and compares it
 * with the initial password hash
 *
 * @param[in]   password: a const string containing a guessed password
 *
 * @return returns true if hashes match; false if generation of hash failed or hashes not match
 */
bool checkPassword(const string &password)
{
#ifdef VERBOSE
    cout << "checking " << password << endl;
#endif // VERBOSE

    // generate sha hash from entered string and write it to pwdHash
    if(!generateSHA256(password.c_str(), password.length(), bruteHash))
    {
        cerr << "Error when generating SHA256 from \"" << password << "\"" << endl;
        return false;
    }

    if (!memcmp(bruteHash, pwdHash, SHA256_DIGEST_LENGTH))
    {
        cout << "match [" << password << "]" << endl << "hash: " << endl;
        printSHAHash((unsigned int*)bruteHash);
        return true;
    }

    return false;
}

/**
 * @brief the main loop for a worker process
 *
 * continuously looks for incoming strings, generates the SHA
 * hash of it and checks if it matches the secret hash
 */
void worker()
{
    char buf[MaxChars];
    MPI_Status state;

    while(true)
    {
        // check for new msg
        MPI_Probe(MasterProcess, MPI_ANY_TAG, MPI_COMM_WORLD, &state);

        int len;
        // now check status to determine how many bytes were actually received
        MPI_Get_count(&state, MPI_BYTE, &len);

        // receive len bytes
        MPI_Recv(buf, len, MPI_BYTE, MasterProcess, MPI_ANY_TAG, MPI_COMM_WORLD, &state);

        string baseStr(buf, len);

        for(int i=0; i<SizeAlphabet; i++)
        {
            if(checkPassword(baseStr+alphabet[i]))
            {
                //success, tell master
                //MPI_Send(const_cast<char*>(baseStr+alphabet[i].c_str()), baseStr+alphabet[i].length(), MPI_CHAR, MasterProcess, success, MPI_COMM_WORLD);
                cout << "Password found: " << baseStr+alphabet[i] << endl;
                MPI_Abort(MPI_COMM_WORLD, 0);

                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_device/android/single_rw_fifo.h"

#include <assert.h>

static int UpdatePos(int pos, int capacity) {
  return (pos + 1) % capacity;
}

namespace webrtc {

namespace subtle {

#if defined(__aarch64__)
// From http://http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_arm64_gcc.h
inline void MemoryBarrier() {
  __asm__ __volatile__ ("dmb ish" ::: "memory");
}

#elif defined(__ARMEL__)
// From http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_arm_gcc.h
inline void MemoryBarrier() {
  // Note: This is a function call, which is also an implicit compiler barrier.
  typedef void (*KernelMemoryBarrierFunc)();
  ((KernelMemoryBarrierFunc)0xffff0fa0)();
}

#elif defined(__x86_64__) || defined (__i386__)
// From http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_x86_gcc.h
// mfence exists on x64 and x86 platforms containing SSE2.
// x86 platforms that don't have SSE2 will crash with SIGILL.
// If this code needs to run on such platforms in the future,
// add runtime CPU detection here.
inline void MemoryBarrier() {
  __asm__ __volatile__("mfence" : : : "memory");
}

#else
#error Add an implementation of MemoryBarrier() for this platform!
#endif

}  // namespace subtle

SingleRwFifo::SingleRwFifo(int capacity)
    : capacity_(capacity),
      size_(0),
      read_pos_(0),
      write_pos_(0) {
  queue_.reset(new int8_t*[capacity_]);
}

SingleRwFifo::~SingleRwFifo() {
}

void SingleRwFifo::Push(int8_t* mem) {
  assert(mem);

  // Ensure that there is space for the new data in the FIFO.
  // Note there is only one writer meaning that the other thread is guaranteed
  // only to decrease the size.
  const int free_slots = capacity() - size();
  if (free_slots <= 0) {
    // Size can be queried outside of the Push function. The caller is assumed
    // to ensure that Push will be successful before calling it.
    assert(false);
    return;
  }
  queue_[write_pos_] = mem;
  // Memory barrier ensures that |size_| is updated after the size has changed.
  subtle::MemoryBarrier();
  ++size_;
  write_pos_ = UpdatePos(write_pos_, capacity());
}

int8_t* SingleRwFifo::Pop() {
  int8_t* ret_val = NULL;
  if (size() <= 0) {
    // Size can be queried outside of the Pop function. The caller is assumed
    // to ensure that Pop will be successfull before calling it.
    assert(false);
    return ret_val;
  }
  ret_val = queue_[read_pos_];
  // Memory barrier ensures that |size_| is updated after the size has changed.
  subtle::MemoryBarrier();
  --size_;
  read_pos_ = UpdatePos(read_pos_, capacity());
  return ret_val;
}

}  // namespace webrtc
<commit_msg>Minor fix for MIPS Android build.<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_device/android/single_rw_fifo.h"

#include <assert.h>

static int UpdatePos(int pos, int capacity) {
  return (pos + 1) % capacity;
}

namespace webrtc {

namespace subtle {

#if defined(__aarch64__)
// From http://http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_arm64_gcc.h
inline void MemoryBarrier() {
  __asm__ __volatile__ ("dmb ish" ::: "memory");
}

#elif defined(__ARMEL__)
// From http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_arm_gcc.h
inline void MemoryBarrier() {
  // Note: This is a function call, which is also an implicit compiler barrier.
  typedef void (*KernelMemoryBarrierFunc)();
  ((KernelMemoryBarrierFunc)0xffff0fa0)();
}

#elif defined(__x86_64__) || defined (__i386__)
// From http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_x86_gcc.h
// mfence exists on x64 and x86 platforms containing SSE2.
// x86 platforms that don't have SSE2 will crash with SIGILL.
// If this code needs to run on such platforms in the future,
// add runtime CPU detection here.
inline void MemoryBarrier() {
  __asm__ __volatile__("mfence" : : : "memory");
}

#elif defined(__MIPSEL__)
// From http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_mips_gcc.h
inline void MemoryBarrier() {
  __asm__ __volatile__("sync" : : : "memory");
}

#else
#error Add an implementation of MemoryBarrier() for this platform!
#endif

}  // namespace subtle

SingleRwFifo::SingleRwFifo(int capacity)
    : capacity_(capacity),
      size_(0),
      read_pos_(0),
      write_pos_(0) {
  queue_.reset(new int8_t*[capacity_]);
}

SingleRwFifo::~SingleRwFifo() {
}

void SingleRwFifo::Push(int8_t* mem) {
  assert(mem);

  // Ensure that there is space for the new data in the FIFO.
  // Note there is only one writer meaning that the other thread is guaranteed
  // only to decrease the size.
  const int free_slots = capacity() - size();
  if (free_slots <= 0) {
    // Size can be queried outside of the Push function. The caller is assumed
    // to ensure that Push will be successful before calling it.
    assert(false);
    return;
  }
  queue_[write_pos_] = mem;
  // Memory barrier ensures that |size_| is updated after the size has changed.
  subtle::MemoryBarrier();
  ++size_;
  write_pos_ = UpdatePos(write_pos_, capacity());
}

int8_t* SingleRwFifo::Pop() {
  int8_t* ret_val = NULL;
  if (size() <= 0) {
    // Size can be queried outside of the Pop function. The caller is assumed
    // to ensure that Pop will be successfull before calling it.
    assert(false);
    return ret_val;
  }
  ret_val = queue_[read_pos_];
  // Memory barrier ensures that |size_| is updated after the size has changed.
  subtle::MemoryBarrier();
  --size_;
  read_pos_ = UpdatePos(read_pos_, capacity());
  return ret_val;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>#include "mmOptionsView.h"

using namespace MoMa;

Options::Options( SceneApp *_app, MoMa::Position position, MoMa::Position alignment, MoMa::Canvas *parentUI, int group, bool minified ) :
    app(_app),
    Canvas( _app, "View Options", position, alignment, NULL, parentUI, group, minified ) {

        /*addLabelToggle( "SHOW 3D SCENE", app->is3dScene );
        addLabelToggle( "SHOW 3D GROUND", app->isGround );
        addLabelToggle( "SHOW NODE NAMES", app->isNodeNames );
        addLabelToggle( "SHOW ANNOTATIONS", app->isAnnotation );
        addLabelToggle( "SHOW 2D FIGURES", app->isFigure );
        addLabelToggle( "SHOW CAPTIONS", app->isCaptions );
        addLabelToggle( "SHOW TIMELINE", app->isTimeline );*/

        addToggle( "Show 3D Scene", app->is3dScene );
        addToggle( "Show 3D Ground", app->isGround );
        addToggle( "Show Node Names", app->isNodeNames );
        addToggle( "Show Annotations", app->isAnnotation );
        addToggle( "Show 2D Figures", app->isFigure );
        addToggle( "Show Captions", app->isCaptions );
        addToggle( "Show Timeline", app->isTimeline );

        //addLabelButton( "RESET OSC", false);

        setVisible(false);
        initCanvas();
}

void Options::canvasEvent( ofxUIEventArgs &e ) {

    string name = e.widget->getName(); // We grab the name and test it
    /*if( e.widget->getKind() == OFX_UI_WIDGET_LABELTOGGLE ) {

        ofxUILabelToggle *toggle = (ofxUILabelToggle *) e.widget; // Toggle

        if( name == "SHOW 3D SCENE" ) app->show3dScene( toggle->getValue() );
        else if( name == "SHOW 3D GROUND" ) app->showGround( toggle->getValue() );
        else if( name == "SHOW NODE NAMES" ) app->showNodeNames( toggle->getValue() );
        else if( name == "SHOW ANNOTATIONS" ) app->showAnnotation( toggle->getValue() );
        else if( name == "SHOW 2D FIGURES" ) app->showFigures( toggle->getValue() );
        else if( name == "SHOW CAPTIONS" ) app->showCaptions( toggle->getValue() );
        else if( name == "SHOW TIMELINE" ) app->showTimeline( toggle->getValue() );
    }*/

    if( e.widget->getKind() == OFX_UI_WIDGET_TOGGLE ) {

        ofxUIToggle *toggle = (ofxUIToggle *) e.widget; // Toggle

        if( name == "Show 3D Scene" ) app->show3dScene( toggle->getValue() );
        else if( name == "Show 3D Ground" ) app->showGround( toggle->getValue() );
        else if( name == "Show Node Names" ) app->showNodeNames( toggle->getValue() );
        else if( name == "Show Annotations" ) app->showAnnotation( toggle->getValue() );
        else if( name == "Show 2D Figures" ) app->showFigures( toggle->getValue() );
        else if( name == "Show Captions" ) app->showCaptions( toggle->getValue() );
        else if( name == "Show Timeline" ) app->showTimeline( toggle->getValue() );
    }

    /*else if(e.widget->getKind() == OFX_UI_WIDGET_LABELBUTTON ) {

        if( name == "RESET OSC" ) {

        }
    }*/
}

void Options::update() {

}<commit_msg>Added a very beautiful spacer in options view<commit_after>#include "mmOptionsView.h"

using namespace MoMa;

Options::Options( SceneApp *_app, MoMa::Position position, MoMa::Position alignment, MoMa::Canvas *parentUI, int group, bool minified ) :
    app(_app),
    Canvas( _app, "View Options", position, alignment, NULL, parentUI, group, minified ) {

        /*addLabelToggle( "SHOW 3D SCENE", app->is3dScene );
        addLabelToggle( "SHOW 3D GROUND", app->isGround );
        addLabelToggle( "SHOW NODE NAMES", app->isNodeNames );
        addLabelToggle( "SHOW ANNOTATIONS", app->isAnnotation );
        addLabelToggle( "SHOW 2D FIGURES", app->isFigure );
        addLabelToggle( "SHOW CAPTIONS", app->isCaptions );
        addLabelToggle( "SHOW TIMELINE", app->isTimeline );*/

        addSpacer();
        addToggle( "Show 3D Scene", app->is3dScene );
        addToggle( "Show 3D Ground", app->isGround );
        addToggle( "Show Node Names", app->isNodeNames );
        addToggle( "Show Annotations", app->isAnnotation );
        addToggle( "Show 2D Figures", app->isFigure );
        addToggle( "Show Captions", app->isCaptions );
        addToggle( "Show Timeline", app->isTimeline );

        //addLabelButton( "RESET OSC", false);

        setVisible(false);
        initCanvas();
}

void Options::canvasEvent( ofxUIEventArgs &e ) {

    string name = e.widget->getName(); // We grab the name and test it
    /*if( e.widget->getKind() == OFX_UI_WIDGET_LABELTOGGLE ) {

        ofxUILabelToggle *toggle = (ofxUILabelToggle *) e.widget; // Toggle

        if( name == "SHOW 3D SCENE" ) app->show3dScene( toggle->getValue() );
        else if( name == "SHOW 3D GROUND" ) app->showGround( toggle->getValue() );
        else if( name == "SHOW NODE NAMES" ) app->showNodeNames( toggle->getValue() );
        else if( name == "SHOW ANNOTATIONS" ) app->showAnnotation( toggle->getValue() );
        else if( name == "SHOW 2D FIGURES" ) app->showFigures( toggle->getValue() );
        else if( name == "SHOW CAPTIONS" ) app->showCaptions( toggle->getValue() );
        else if( name == "SHOW TIMELINE" ) app->showTimeline( toggle->getValue() );
    }*/

    if( e.widget->getKind() == OFX_UI_WIDGET_TOGGLE ) {

        ofxUIToggle *toggle = (ofxUIToggle *) e.widget; // Toggle

        if( name == "Show 3D Scene" ) app->show3dScene( toggle->getValue() );
        else if( name == "Show 3D Ground" ) app->showGround( toggle->getValue() );
        else if( name == "Show Node Names" ) app->showNodeNames( toggle->getValue() );
        else if( name == "Show Annotations" ) app->showAnnotation( toggle->getValue() );
        else if( name == "Show 2D Figures" ) app->showFigures( toggle->getValue() );
        else if( name == "Show Captions" ) app->showCaptions( toggle->getValue() );
        else if( name == "Show Timeline" ) app->showTimeline( toggle->getValue() );
    }

    /*else if(e.widget->getKind() == OFX_UI_WIDGET_LABELBUTTON ) {

        if( name == "RESET OSC" ) {

        }
    }*/
}

void Options::update() {

}<|endoftext|>


<commit_before>/*
 * opencog/attentionbank/AttentionBank.cc
 *
 * Copyright (C) 2013,2017 Linas Vepstas <linasvepstas@gmail.com>
 * All Rights Reserved
 *
 * Written by Joel Pitt
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <functional>
#include <opencog/util/Config.h>

#include <opencog/atoms/base/Handle.h>
#include <opencog/atomspace/AtomSpace.h>
#include "AttentionBank.h"
#include "AVUtils.h"

using namespace opencog;

AttentionBank::AttentionBank(AtomSpace* asp)
{
    startingFundsSTI = fundsSTI = config().get_int("STARTING_STI_FUNDS", 100000);
    startingFundsLTI = fundsLTI = config().get_int("STARTING_LTI_FUNDS", 100000);
    stiFundsBuffer = config().get_int("STI_FUNDS_BUFFER", 10000);
    ltiFundsBuffer = config().get_int("LTI_FUNDS_BUFFER", 10000);
    targetLTI = config().get_int("TARGET_LTI_FUNDS", 10000);
    targetSTI = config().get_int("TARGET_STI_FUNDS", 10000);
    STIAtomWage = config().get_int("ECAN_STARTING_ATOM_STI_WAGE", 10);
    LTIAtomWage = config().get_int("ECAN_STARTING_ATOM_LTI_WAGE", 10);
    minAFSize = config().get_int("ECAN_MIN_AF_SIZE", 100);

    _remove_signal = &asp->atomRemovedSignal();
    _remove_connection = _remove_signal->connect(
            std::bind(&AttentionBank::remove_atom_from_bank, this,
                std::placeholders::_1));
}

AttentionBank::~AttentionBank()
{
    //_remove_signal->disconnect(_remove_connection);
}

void AttentionBank::remove_atom_from_bank(const AtomPtr& atom)
{
    _importanceIndex.removeAtom(Handle(atom));
}

void AttentionBank::set_sti(const Handle& h, AttentionValue::sti_t stiValue)
{
    AttentionValuePtr oldav = get_av(h);
    AttentionValuePtr newav = AttentionValue::createAV(
        stiValue, oldav->getLTI(), oldav->getVLTI());

    _importanceIndex.updateImportance(h, oldav, newav);
    AVChanged(h, oldav, newav);
}

void AttentionBank::set_lti(const Handle& h, AttentionValue::lti_t ltiValue)
{
    AttentionValuePtr old_av = get_av(h);
    AttentionValuePtr new_av = AttentionValue::createAV(
        old_av->getSTI(), ltiValue, old_av->getVLTI());

    AVChanged(h, old_av, new_av);
}

void AttentionBank::change_vlti(const Handle& h, int unit)
{
    AttentionValuePtr old_av = get_av(h);
    AttentionValuePtr new_av = AttentionValue::createAV(
        old_av->getSTI(),
        old_av->getLTI(),
        old_av->getVLTI() + unit);

    AVChanged(h, old_av, new_av);
}

void AttentionBank::change_av(const Handle& h, const AttentionValuePtr& new_av)
{
    AttentionValuePtr old_av = get_av(h);
    _importanceIndex.updateImportance(h, old_av, new_av);
    AVChanged(h, old_av, new_av);
}

void AttentionBank::AVChanged(const Handle& h,
                              const AttentionValuePtr& old_av,
                              const AttentionValuePtr& new_av)
{
    // First, update the atom's actual AV.
    set_av(h, new_av);

    AttentionValue::sti_t oldSti = old_av->getSTI();
    AttentionValue::sti_t newSti = new_av->getSTI();

    // Add the old attention values to the AttentionBank funds and
    // subtract the new attention values from the AttentionBank funds
    updateSTIFunds(oldSti - newSti);
    updateLTIFunds(old_av->getLTI() - new_av->getLTI());

    _importanceIndex.update();

    logger().fine("AVChanged: fundsSTI = %d, old_av: %d, new_av: %d",
                   fundsSTI.load(), oldSti, newSti);

    // Notify any interested parties that the AV changed.
    _AVChangedSignal.emit(h, old_av, new_av);

    // update AF
    updateAttentionalFocus(h, old_av, new_av);
}

void AttentionBank::stimulate(const Handle& h, double stimulus)
{
    // XXX This is not protected or made atomic in any way ...
    // If two different threads stimulate the same atom at the same
    // time, then the calculations will be bad. Does it matter?
    if(stimulusRec.find(h) != stimulusRec.end()){
        stimulusRec[h] += stimulus;
    } else{
        stimulusRec[h] = stimulus;
    }

    AttentionValuePtr oldav(get_av(h));
    AttentionValue::sti_t sti   = oldav->getSTI();
    AttentionValue::lti_t lti   = oldav->getLTI();
    AttentionValue::vlti_t vlti = oldav->getVLTI();

    AttentionValue::sti_t stiWage = calculateSTIWage() * stimulus;
    AttentionValue::lti_t ltiWage = calculateLTIWage() * stimulus;
    AttentionValuePtr newav = AttentionValue::createAV(
           sti + stiWage, lti + ltiWage, vlti);
    _importanceIndex.updateImportance(h, oldav, newav);
    AVChanged(h, oldav, newav);
}

AttentionValue::sti_t AttentionBank::calculateSTIWage()
{
    long funds = getSTIFunds();
    double diff  = funds - targetSTI;
    double ndiff = diff / stiFundsBuffer;
    ndiff = std::min(ndiff, 1.0);
    ndiff = std::max(ndiff, -1.0);

    return STIAtomWage + (STIAtomWage * ndiff);
}

AttentionValue::lti_t AttentionBank::calculateLTIWage()
{
    long funds = getLTIFunds();
    double diff  = funds - targetLTI;
    double ndiff = diff / ltiFundsBuffer;
    ndiff = std::min(ndiff, 1.0);
    ndiff = std::max(ndiff, -1.0);

    return LTIAtomWage + (LTIAtomWage * ndiff);
}

double AttentionBank::getNormalisedSTI(AttentionValuePtr av,
                                   bool average, bool clip) const
{
    double val;
    // get normalizer (maxSTI - attention boundary)
    AttentionValue::sti_t s = av->getSTI();
    if (s > get_af_max_sti()) {
        int normaliser = (int) getMaxSTI(average) - get_af_max_sti();
        if (normaliser == 0) return 0.0;
        val = (s - get_af_max_sti()) / (double) normaliser;
    } else {
        int normaliser = -((int) getMinSTI(average) + get_af_max_sti());
        if (normaliser == 0) return 0.0;
        val = (s + get_af_max_sti()) / (double) normaliser;
    }

    if (clip) return std::max(-1.0, std::min(val, 1.0));
    return val;
}

double AttentionBank::getNormalisedSTI(AttentionValuePtr av) const
{
    AttentionValue::sti_t s = av->getSTI();
    auto normaliser =
            s > get_af_max_sti() ? getMaxSTI() : getMinSTI();

    return (s / normaliser);
}

double AttentionBank::getNormalisedZeroToOneSTI(AttentionValuePtr av,
                                    bool average, bool clip) const
{
    AttentionValue::sti_t s = av->getSTI();
    int normaliser = getMaxSTI(average) - getMinSTI(average);

    if (normaliser == 0) return 0.0;

    double val = (s - getMinSTI(average)) / (double) normaliser;
    if (clip) return std::max(0.0, std::min(val, 1.0));
    return val;
}

/** Unique singleton instance (for now) */
// This implementation is pretty hokey, and is a stop-gap until some
// sort of more elegant way of managing the attentionbank is found.
// One of the issues is that access via this function can be CPU-wasteful.
AttentionBank& opencog::attentionbank(AtomSpace* asp)
{
    static AttentionBank* _instance = nullptr;
    static AtomSpace* _as = nullptr;

    // Protect setting and getting against thread races.
    // This is probably not needed.
    static std::map<AtomSpace*, AttentionBank*> banksy;
    static std::mutex art;
    std::unique_lock<std::mutex> graffiti(art);

    if (_as != asp and _instance) {
        delete _instance;
        _instance = nullptr;
        _as = nullptr;
    }
    if (asp and nullptr == _instance) {
        _instance = new AttentionBank(asp);
        _as = asp;
    }
    return *_instance;
}

bool AttentionBank::atom_is_in_AF(const Handle& h)
{
    auto it = std::find_if(attentionalFocus.begin(), attentionalFocus.end(),
            [h](std::pair<Handle, AttentionValuePtr> p)
            {
               if (p.first == h) return true;
               return false;
            });
    return  (it != attentionalFocus.end());
}

/**
 *  Updates list of top K important atoms based on STI value.
 */
void AttentionBank::updateAttentionalFocus(const Handle& h,
                    const AttentionValuePtr& old_av,
                    const AttentionValuePtr& new_av)
{
    std::lock_guard<std::mutex> lock(AFMutex);
    AttentionValue::sti_t sti = new_av->getSTI();
    auto least = attentionalFocus.begin(); // Atom to be removed from the AF
    bool insertable = false;
    auto it = std::find_if(attentionalFocus.begin(), attentionalFocus.end(),
            [h](std::pair<Handle, AttentionValuePtr> p)
            { if (p.first == h) return true; return false;});

    // Update the STI value if atoms was already in AF
    if (it != attentionalFocus.end())
    {
        attentionalFocus.erase(it);
        attentionalFocus.insert(std::make_pair(h, new_av));
        return;
    }

    // Simply insert the new Atom if AF is not full yet.
    else if (attentionalFocus.size() < minAFSize)
    {
        insertable = true;
    }

    // Remove the least sti valued atom in the AF and repace
    // it with the new atom holding higher STI value.
    else if (sti > (least->second)->getSTI())
    {
        Handle hrm = least->first;
        AttentionValuePtr hrm_new_av = get_av(hrm);
        // Value recorded when this atom entered into AF
        AttentionValuePtr hrm_old_av = least->second;

        attentionalFocus.erase(least);
        AFCHSigl& afch = RemoveAFSignal();
        afch.emit(hrm, hrm_old_av, hrm_new_av);
        insertable = true;
    }

    // Insert the new atom in to AF and emit the AddAFSignal.
    if (insertable)
    {
        attentionalFocus.insert(std::make_pair(h, new_av));
        AFCHSigl& afch = AddAFSignal();
        afch.emit(h, old_av, new_av);
    }
}
<commit_msg>Move code below the comment<commit_after>/*
 * opencog/attentionbank/AttentionBank.cc
 *
 * Copyright (C) 2013,2017 Linas Vepstas <linasvepstas@gmail.com>
 * All Rights Reserved
 *
 * Written by Joel Pitt
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <functional>
#include <opencog/util/Config.h>

#include <opencog/atoms/base/Handle.h>
#include <opencog/atomspace/AtomSpace.h>
#include "AttentionBank.h"
#include "AVUtils.h"

using namespace opencog;

AttentionBank::AttentionBank(AtomSpace* asp)
{
    startingFundsSTI = fundsSTI = config().get_int("STARTING_STI_FUNDS", 100000);
    startingFundsLTI = fundsLTI = config().get_int("STARTING_LTI_FUNDS", 100000);
    stiFundsBuffer = config().get_int("STI_FUNDS_BUFFER", 10000);
    ltiFundsBuffer = config().get_int("LTI_FUNDS_BUFFER", 10000);
    targetLTI = config().get_int("TARGET_LTI_FUNDS", 10000);
    targetSTI = config().get_int("TARGET_STI_FUNDS", 10000);
    STIAtomWage = config().get_int("ECAN_STARTING_ATOM_STI_WAGE", 10);
    LTIAtomWage = config().get_int("ECAN_STARTING_ATOM_LTI_WAGE", 10);
    minAFSize = config().get_int("ECAN_MIN_AF_SIZE", 100);

    _remove_signal = &asp->atomRemovedSignal();
    _remove_connection = _remove_signal->connect(
            std::bind(&AttentionBank::remove_atom_from_bank, this,
                std::placeholders::_1));
}

AttentionBank::~AttentionBank()
{
    //_remove_signal->disconnect(_remove_connection);
}

void AttentionBank::remove_atom_from_bank(const AtomPtr& atom)
{
    _importanceIndex.removeAtom(Handle(atom));
}

void AttentionBank::set_sti(const Handle& h, AttentionValue::sti_t stiValue)
{
    AttentionValuePtr oldav = get_av(h);
    AttentionValuePtr newav = AttentionValue::createAV(
        stiValue, oldav->getLTI(), oldav->getVLTI());

    _importanceIndex.updateImportance(h, oldav, newav);
    AVChanged(h, oldav, newav);
}

void AttentionBank::set_lti(const Handle& h, AttentionValue::lti_t ltiValue)
{
    AttentionValuePtr old_av = get_av(h);
    AttentionValuePtr new_av = AttentionValue::createAV(
        old_av->getSTI(), ltiValue, old_av->getVLTI());

    AVChanged(h, old_av, new_av);
}

void AttentionBank::change_vlti(const Handle& h, int unit)
{
    AttentionValuePtr old_av = get_av(h);
    AttentionValuePtr new_av = AttentionValue::createAV(
        old_av->getSTI(),
        old_av->getLTI(),
        old_av->getVLTI() + unit);

    AVChanged(h, old_av, new_av);
}

void AttentionBank::change_av(const Handle& h, const AttentionValuePtr& new_av)
{
    AttentionValuePtr old_av = get_av(h);
    _importanceIndex.updateImportance(h, old_av, new_av);
    AVChanged(h, old_av, new_av);
}

void AttentionBank::AVChanged(const Handle& h,
                              const AttentionValuePtr& old_av,
                              const AttentionValuePtr& new_av)
{
    // First, update the atom's actual AV.
    set_av(h, new_av);

    AttentionValue::sti_t oldSti = old_av->getSTI();
    AttentionValue::sti_t newSti = new_av->getSTI();

    // Add the old attention values to the AttentionBank funds and
    // subtract the new attention values from the AttentionBank funds
    updateSTIFunds(oldSti - newSti);
    updateLTIFunds(old_av->getLTI() - new_av->getLTI());

    _importanceIndex.update();

    logger().fine("AVChanged: fundsSTI = %d, old_av: %d, new_av: %d",
                   fundsSTI.load(), oldSti, newSti);

    // Notify any interested parties that the AV changed.
    _AVChangedSignal.emit(h, old_av, new_av);

    // update AF
    updateAttentionalFocus(h, old_av, new_av);
}

void AttentionBank::stimulate(const Handle& h, double stimulus)
{
    // XXX This is not protected or made atomic in any way ...
    // If two different threads stimulate the same atom at the same
    // time, then the calculations will be bad. Does it matter?
    AttentionValuePtr oldav(get_av(h));
    AttentionValue::sti_t sti   = oldav->getSTI();
    AttentionValue::lti_t lti   = oldav->getLTI();
    AttentionValue::vlti_t vlti = oldav->getVLTI();

    AttentionValue::sti_t stiWage = calculateSTIWage() * stimulus;
    AttentionValue::lti_t ltiWage = calculateLTIWage() * stimulus;
    AttentionValuePtr newav = AttentionValue::createAV(
           sti + stiWage, lti + ltiWage, vlti);
    _importanceIndex.updateImportance(h, oldav, newav);
    AVChanged(h, oldav, newav);

    if(stimulusRec.find(h) != stimulusRec.end()){
        stimulusRec[h] += stimulus;
    } else{
        stimulusRec[h] = stimulus;
    }
}

AttentionValue::sti_t AttentionBank::calculateSTIWage()
{
    long funds = getSTIFunds();
    double diff  = funds - targetSTI;
    double ndiff = diff / stiFundsBuffer;
    ndiff = std::min(ndiff, 1.0);
    ndiff = std::max(ndiff, -1.0);

    return STIAtomWage + (STIAtomWage * ndiff);
}

AttentionValue::lti_t AttentionBank::calculateLTIWage()
{
    long funds = getLTIFunds();
    double diff  = funds - targetLTI;
    double ndiff = diff / ltiFundsBuffer;
    ndiff = std::min(ndiff, 1.0);
    ndiff = std::max(ndiff, -1.0);

    return LTIAtomWage + (LTIAtomWage * ndiff);
}

double AttentionBank::getNormalisedSTI(AttentionValuePtr av,
                                   bool average, bool clip) const
{
    double val;
    // get normalizer (maxSTI - attention boundary)
    AttentionValue::sti_t s = av->getSTI();
    if (s > get_af_max_sti()) {
        int normaliser = (int) getMaxSTI(average) - get_af_max_sti();
        if (normaliser == 0) return 0.0;
        val = (s - get_af_max_sti()) / (double) normaliser;
    } else {
        int normaliser = -((int) getMinSTI(average) + get_af_max_sti());
        if (normaliser == 0) return 0.0;
        val = (s + get_af_max_sti()) / (double) normaliser;
    }

    if (clip) return std::max(-1.0, std::min(val, 1.0));
    return val;
}

double AttentionBank::getNormalisedSTI(AttentionValuePtr av) const
{
    AttentionValue::sti_t s = av->getSTI();
    auto normaliser =
            s > get_af_max_sti() ? getMaxSTI() : getMinSTI();

    return (s / normaliser);
}

double AttentionBank::getNormalisedZeroToOneSTI(AttentionValuePtr av,
                                    bool average, bool clip) const
{
    AttentionValue::sti_t s = av->getSTI();
    int normaliser = getMaxSTI(average) - getMinSTI(average);

    if (normaliser == 0) return 0.0;

    double val = (s - getMinSTI(average)) / (double) normaliser;
    if (clip) return std::max(0.0, std::min(val, 1.0));
    return val;
}

/** Unique singleton instance (for now) */
// This implementation is pretty hokey, and is a stop-gap until some
// sort of more elegant way of managing the attentionbank is found.
// One of the issues is that access via this function can be CPU-wasteful.
AttentionBank& opencog::attentionbank(AtomSpace* asp)
{
    static AttentionBank* _instance = nullptr;
    static AtomSpace* _as = nullptr;

    // Protect setting and getting against thread races.
    // This is probably not needed.
    static std::map<AtomSpace*, AttentionBank*> banksy;
    static std::mutex art;
    std::unique_lock<std::mutex> graffiti(art);

    if (_as != asp and _instance) {
        delete _instance;
        _instance = nullptr;
        _as = nullptr;
    }
    if (asp and nullptr == _instance) {
        _instance = new AttentionBank(asp);
        _as = asp;
    }
    return *_instance;
}

bool AttentionBank::atom_is_in_AF(const Handle& h)
{
    auto it = std::find_if(attentionalFocus.begin(), attentionalFocus.end(),
            [h](std::pair<Handle, AttentionValuePtr> p)
            {
               if (p.first == h) return true;
               return false;
            });
    return  (it != attentionalFocus.end());
}

/**
 *  Updates list of top K important atoms based on STI value.
 */
void AttentionBank::updateAttentionalFocus(const Handle& h,
                    const AttentionValuePtr& old_av,
                    const AttentionValuePtr& new_av)
{
    std::lock_guard<std::mutex> lock(AFMutex);
    AttentionValue::sti_t sti = new_av->getSTI();
    auto least = attentionalFocus.begin(); // Atom to be removed from the AF
    bool insertable = false;
    auto it = std::find_if(attentionalFocus.begin(), attentionalFocus.end(),
            [h](std::pair<Handle, AttentionValuePtr> p)
            { if (p.first == h) return true; return false;});

    // Update the STI value if atoms was already in AF
    if (it != attentionalFocus.end())
    {
        attentionalFocus.erase(it);
        attentionalFocus.insert(std::make_pair(h, new_av));
        return;
    }

    // Simply insert the new Atom if AF is not full yet.
    else if (attentionalFocus.size() < minAFSize)
    {
        insertable = true;
    }

    // Remove the least sti valued atom in the AF and repace
    // it with the new atom holding higher STI value.
    else if (sti > (least->second)->getSTI())
    {
        Handle hrm = least->first;
        AttentionValuePtr hrm_new_av = get_av(hrm);
        // Value recorded when this atom entered into AF
        AttentionValuePtr hrm_old_av = least->second;

        attentionalFocus.erase(least);
        AFCHSigl& afch = RemoveAFSignal();
        afch.emit(hrm, hrm_old_av, hrm_new_av);
        insertable = true;
    }

    // Insert the new atom in to AF and emit the AddAFSignal.
    if (insertable)
    {
        attentionalFocus.insert(std::make_pair(h, new_av));
        AFCHSigl& afch = AddAFSignal();
        afch.emit(h, old_av, new_av);
    }
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
////////////////////////////////////////////////////////////////////////////////

#include "VstResponse.h"

#include <velocypack/Builder.h>
#include <velocypack/Dumper.h>
#include <velocypack/Options.h>
#include <velocypack/velocypack-aliases.h>

#include "Basics/Exceptions.h"
#include "Basics/StringBuffer.h"
#include "Basics/StringUtils.h"
#include "Basics/VPackStringBufferAdapter.h"
#include "Basics/tri-strings.h"
#include "Meta/conversion.h"
#include "Rest/VstRequest.h"

using namespace arangodb;
using namespace arangodb::basics;

bool VstResponse::HIDE_PRODUCT_HEADER = false;

VstResponse::VstResponse(ResponseCode code, uint64_t id)
    : GeneralResponse(code), _messageId(id), _header(nullptr) {
  _contentType = ContentType::VPACK;
  _connectionType = rest::ConnectionType::C_KEEP_ALIVE;
}

void VstResponse::reset(ResponseCode code) {
  _responseCode = code;
  _headers.clear();
  _connectionType = rest::ConnectionType::C_KEEP_ALIVE;
  _contentType = ContentType::VPACK;
  _generateBody = false;  // payload has to be set
}

void VstResponse::addPayload(VPackSlice const& slice,
                             velocypack::Options const* options,
                             bool resolveExternals) {
  if (!options) {
    options = &VPackOptions::Options::Defaults;
  }

  // only copy buffer if it contains externals
  if (resolveExternals) {
    bool resolveExt = VelocyPackHelper::hasNonClientTypes(slice, true, true);
    if (resolveExt) {  // resolve
      VPackBuffer<uint8_t> tmpBuffer;
      tmpBuffer.reserve(slice.byteSize()); // reserve space already
      VPackBuilder builder(tmpBuffer, options);
      VelocyPackHelper::sanitizeNonClientTypes(slice, VPackSlice::noneSlice(),
                                               builder, options, true, true);
      _vpackPayloads.push_back(std::move(tmpBuffer));
    } else {
      // just copy
      _vpackPayloads.emplace_back(slice.byteSize());
      _vpackPayloads.back().append(slice.startAs<char const>(),
                                   slice.byteSize());
    }
  } else {
    // just copy
    _vpackPayloads.emplace_back(slice.byteSize());
    _vpackPayloads.back().append(slice.startAs<char const>(),
                                 slice.byteSize());
  }
}

void VstResponse::addPayload(VPackBuffer<uint8_t>&& buffer,
                             velocypack::Options const* options,
                             bool resolveExternals) {
  if (!options) {
    options = &VPackOptions::Options::Defaults;
  }

  // only copy buffer if it contains externals
  if (resolveExternals) {
    VPackSlice input(buffer.data());
    bool resolveExt = VelocyPackHelper::hasNonClientTypes(input, true, true);
    if (resolveExt) {  // resolve
      VPackBuffer<uint8_t> tmpBuffer;
      tmpBuffer.reserve(buffer.length()); // reserve space already
      VPackBuilder builder(tmpBuffer, options);
      VelocyPackHelper::sanitizeNonClientTypes(input, VPackSlice::noneSlice(),
                                               builder, options, true, true);
      _vpackPayloads.push_back(std::move(tmpBuffer));
    } else {
      _vpackPayloads.push_back(std::move(buffer));
    }
  } else {
    _vpackPayloads.push_back(std::move(buffer));
  }
}

VPackMessageNoOwnBuffer VstResponse::prepareForNetwork() {
  // initialize builder with vpackbuffer. then we do not need to
  // steal the header and can avoid the shared pointer
  VPackBuilder builder;
  builder.openArray();
  builder.add(VPackValue(int(1)));  // 1 == version
  builder.add(VPackValue(int(2)));  // 2 == response
  builder.add(VPackValue(static_cast<int>(meta::underlyingValue(_responseCode)))); // 3 == request - return code

  std::string currentHeader;
  builder.openObject(); // 4 == meta
  for (auto& item : _headers) {
    currentHeader.assign(item.first);
    int capState = 1;
    for (auto& it : currentHeader) {
      if (capState == 1) {
        // upper case
        it = ::toupper(it);
        capState = 0;
      } else if (capState == 0) {
        // normal case
        it = ::tolower(it);
        if (it == '-') {
          capState = 1;
        } else if (it == ':') {
          capState = 2;
        }
      }
    }
    builder.add(currentHeader, VPackValue(item.second));
  }
  builder.close();

  builder.close();
  _header = builder.steal();
  if (_vpackPayloads.empty()) {
    if (_generateBody) {
      LOG_TOPIC(INFO, Logger::REQUESTS)
          << "Response should generate body but no Data available";
      _generateBody = false;  // no body availalbe
    }
    return VPackMessageNoOwnBuffer(VPackSlice(_header->data()),
                                   VPackSlice::noneSlice(), _messageId,
                                   _generateBody);
  } else {
    std::vector<VPackSlice> slices;
    for (auto const& buffer : _vpackPayloads) {
      slices.emplace_back(buffer.data());
    }
    return VPackMessageNoOwnBuffer(VPackSlice(_header->data()),
                                   std::move(slices), _messageId,
                                   _generateBody);
  }
}
<commit_msg>simplify code a bit (#4936)<commit_after>///////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
////////////////////////////////////////////////////////////////////////////////

#include "VstResponse.h"

#include <velocypack/Builder.h>
#include <velocypack/Dumper.h>
#include <velocypack/Options.h>
#include <velocypack/velocypack-aliases.h>

#include "Basics/Exceptions.h"
#include "Basics/StringBuffer.h"
#include "Basics/StringUtils.h"
#include "Basics/VPackStringBufferAdapter.h"
#include "Basics/tri-strings.h"
#include "Meta/conversion.h"
#include "Rest/VstRequest.h"

using namespace arangodb;
using namespace arangodb::basics;

bool VstResponse::HIDE_PRODUCT_HEADER = false;

VstResponse::VstResponse(ResponseCode code, uint64_t id)
    : GeneralResponse(code), _messageId(id), _header(nullptr) {
  _contentType = ContentType::VPACK;
  _connectionType = rest::ConnectionType::C_KEEP_ALIVE;
}

void VstResponse::reset(ResponseCode code) {
  _responseCode = code;
  _headers.clear();
  _connectionType = rest::ConnectionType::C_KEEP_ALIVE;
  _contentType = ContentType::VPACK;
  _generateBody = false;  // payload has to be set
}

void VstResponse::addPayload(VPackSlice const& slice,
                             velocypack::Options const* options,
                             bool resolveExternals) {
  if (!options) {
    options = &VPackOptions::Options::Defaults;
  }

  // only copy buffer if it contains externals
  if (resolveExternals) {
    bool resolveExt = VelocyPackHelper::hasNonClientTypes(slice, true, true);
    if (resolveExt) {  // resolve
      VPackBuffer<uint8_t> tmpBuffer;
      tmpBuffer.reserve(slice.byteSize()); // reserve space already
      VPackBuilder builder(tmpBuffer, options);
      VelocyPackHelper::sanitizeNonClientTypes(slice, VPackSlice::noneSlice(),
                                               builder, options, true, true);
      _vpackPayloads.push_back(std::move(tmpBuffer));
      return;
    }
  }

  // just copy
  _vpackPayloads.emplace_back(slice.byteSize());
  _vpackPayloads.back().append(slice.startAs<char const>(),
                               slice.byteSize());
}

void VstResponse::addPayload(VPackBuffer<uint8_t>&& buffer,
                             velocypack::Options const* options,
                             bool resolveExternals) {
  if (!options) {
    options = &VPackOptions::Options::Defaults;
  }

  // only copy buffer if it contains externals
  if (resolveExternals) {
    VPackSlice input(buffer.data());
    bool resolveExt = VelocyPackHelper::hasNonClientTypes(input, true, true);
    if (resolveExt) {  // resolve
      VPackBuffer<uint8_t> tmpBuffer;
      tmpBuffer.reserve(buffer.length()); // reserve space already
      VPackBuilder builder(tmpBuffer, options);
      VelocyPackHelper::sanitizeNonClientTypes(input, VPackSlice::noneSlice(),
                                               builder, options, true, true);
      _vpackPayloads.push_back(std::move(tmpBuffer));
      return;
    }
  }
  _vpackPayloads.push_back(std::move(buffer));
}

VPackMessageNoOwnBuffer VstResponse::prepareForNetwork() {
  // initialize builder with vpackbuffer. then we do not need to
  // steal the header and can avoid the shared pointer
  VPackBuilder builder;
  builder.openArray();
  builder.add(VPackValue(int(1)));  // 1 == version
  builder.add(VPackValue(int(2)));  // 2 == response
  builder.add(VPackValue(static_cast<int>(meta::underlyingValue(_responseCode)))); // 3 == request - return code

  std::string currentHeader;
  builder.openObject(); // 4 == meta
  for (auto& item : _headers) {
    currentHeader.assign(item.first);
    int capState = 1;
    for (auto& it : currentHeader) {
      if (capState == 1) {
        // upper case
        it = ::toupper(it);
        capState = 0;
      } else if (capState == 0) {
        // normal case
        it = ::tolower(it);
        if (it == '-') {
          capState = 1;
        } else if (it == ':') {
          capState = 2;
        }
      }
    }
    builder.add(currentHeader, VPackValue(item.second));
  }
  builder.close();

  builder.close();
  _header = builder.steal();
  if (_vpackPayloads.empty()) {
    if (_generateBody) {
      LOG_TOPIC(INFO, Logger::REQUESTS)
          << "Response should generate body but no Data available";
      _generateBody = false;  // no body availalbe
    }
    return VPackMessageNoOwnBuffer(VPackSlice(_header->data()),
                                   VPackSlice::noneSlice(), _messageId,
                                   _generateBody);
  } else {
    std::vector<VPackSlice> slices;
    for (auto const& buffer : _vpackPayloads) {
      slices.emplace_back(buffer.data());
    }
    return VPackMessageNoOwnBuffer(VPackSlice(_header->data()),
                                   std::move(slices), _messageId,
                                   _generateBody);
  }
}
<|endoftext|>