<commit_before>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "FdIstream.hxx"
#include "istream.hxx"
#include "New.hxx"
#include "Result.hxx"
#include "io/Buffered.hxx"
#include "io/UniqueFileDescriptor.hxx"
#include "pool/pool.hxx"
#include "fb_pool.hxx"
#include "SliceFifoBuffer.hxx"
#include "system/Error.hxx"
#include "event/TimerEvent.hxx"

#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>

/**
 * If EAGAIN occurs (on NFS), we try again after 100ms.  We can't
 * check SocketEvent::READ, because the kernel always indicates VFS files as
 * "readable without blocking".
 */
static constexpr Event::Duration file_retry_timeout = std::chrono::milliseconds(100);

class FdIstream final : public Istream {
	UniqueFileDescriptor fd;

	FdType fd_type;

	bool eof = false;

	/**
	 * A timer to retry reading after EAGAIN.
	 */
	TimerEvent retry_event;

	SliceFifoBuffer buffer;
	const char *path;

public:
	FdIstream(struct pool &p, EventLoop &event_loop,
		  UniqueFileDescriptor &&_fd, FdType _fd_type,
		  const char *_path) noexcept
		:Istream(p),
		 fd(std::move(_fd)), fd_type(_fd_type),
		 retry_event(event_loop, BIND_THIS_METHOD(EventCallback)),
		 path(_path) {}

	~FdIstream() noexcept {
		buffer.FreeIfDefined();
	}

private:
	void TryData() noexcept;
	void TryDirect() noexcept;

	void TryRead() noexcept {
		if (!fd.IsDefined())
			SendFromBuffer(buffer);
		else if (CheckDirect(fd_type))
			TryDirect();
		else
			TryData();
	}

	void EventCallback() noexcept {
		TryRead();
	}

	/* virtual methods from class Istream */

	off_t _GetAvailable(bool partial) noexcept override;

	void _Read() noexcept override {
		retry_event.Cancel();
		TryRead();
	}

	int _AsFd() noexcept override;
	void _Close() noexcept override {
		Destroy();
	}
};

inline void
FdIstream::TryData() noexcept
{
	if (buffer.IsNull()) {
		buffer.Allocate(fb_pool_get());
	} else {
		const size_t available = buffer.GetAvailable();
		if (available > 0) {
			if (SendFromBuffer(buffer) == 0)
				/* not a single byte was consumed: we may have been
				   closed, and we must bail out now */
				return;
		}
	}

	ssize_t nbytes = read_to_buffer(fd.Get(), buffer, INT_MAX);
	if (nbytes == 0) {
		fd.Close();
		if (buffer.empty())
			DestroyEof();
		return;
	} else if (nbytes == -1) {
		DestroyError(std::make_exception_ptr(FormatErrno("Failed to read from '%s'",
								 path)));
		return;
	}

	assert(!buffer.empty());

	SendFromBuffer(buffer);
}

inline void
FdIstream::TryDirect() noexcept
{
	/* first consume the rest of the buffer */
	if (ConsumeFromBuffer(buffer) > 0)
		return;

	ssize_t nbytes = InvokeDirect(fd_type, fd.Get(), INT_MAX);
	if (nbytes == ISTREAM_RESULT_CLOSED)
		/* this stream was closed during the direct() callback */
		return;

	if (nbytes > 0 || nbytes == ISTREAM_RESULT_BLOCKING) {
	} else if (nbytes == ISTREAM_RESULT_EOF) {
		DestroyEof();
	} else if (errno == EAGAIN) {
		/* this should only happen for splice(SPLICE_F_NONBLOCK) from
		   NFS files - unfortunately we cannot use SocketEvent::READ
		   here, so we just install a timer which retries after
		   100ms */

		retry_event.Schedule(file_retry_timeout);
	} else {
		/* XXX */
		DestroyError(std::make_exception_ptr(FormatErrno("Failed to read from '%s'",
								 path)));
	}
}

/*
 * istream implementation
 *
 */

off_t
FdIstream::_GetAvailable(bool partial) noexcept
{
	return partial
		? buffer.GetAvailable()
		: -1;
}

int
FdIstream::_AsFd() noexcept
{
	if (!fd.IsDefined())
		return -1;

	int result_fd = fd.Steal();
	Destroy();
	return result_fd;
}

/*
 * constructor and public methods
 *
 */

UnusedIstreamPtr
NewFdIstream(EventLoop &event_loop, struct pool &pool,
	     const char *path,
	     UniqueFileDescriptor fd, FdType fd_type) noexcept
{
	assert(fd.IsDefined());

	return NewIstreamPtr<FdIstream>(pool, event_loop,
					std::move(fd), fd_type, path);
}
<commit_msg>istream/fd: remove unused field `eof`<commit_after>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "FdIstream.hxx"
#include "istream.hxx"
#include "New.hxx"
#include "Result.hxx"
#include "io/Buffered.hxx"
#include "io/UniqueFileDescriptor.hxx"
#include "pool/pool.hxx"
#include "fb_pool.hxx"
#include "SliceFifoBuffer.hxx"
#include "system/Error.hxx"
#include "event/TimerEvent.hxx"

#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>

/**
 * If EAGAIN occurs (on NFS), we try again after 100ms.  We can't
 * check SocketEvent::READ, because the kernel always indicates VFS files as
 * "readable without blocking".
 */
static constexpr Event::Duration file_retry_timeout = std::chrono::milliseconds(100);

class FdIstream final : public Istream {
	UniqueFileDescriptor fd;

	FdType fd_type;

	/**
	 * A timer to retry reading after EAGAIN.
	 */
	TimerEvent retry_event;

	SliceFifoBuffer buffer;
	const char *path;

public:
	FdIstream(struct pool &p, EventLoop &event_loop,
		  UniqueFileDescriptor &&_fd, FdType _fd_type,
		  const char *_path) noexcept
		:Istream(p),
		 fd(std::move(_fd)), fd_type(_fd_type),
		 retry_event(event_loop, BIND_THIS_METHOD(EventCallback)),
		 path(_path) {}

	~FdIstream() noexcept {
		buffer.FreeIfDefined();
	}

private:
	void TryData() noexcept;
	void TryDirect() noexcept;

	void TryRead() noexcept {
		if (!fd.IsDefined())
			SendFromBuffer(buffer);
		else if (CheckDirect(fd_type))
			TryDirect();
		else
			TryData();
	}

	void EventCallback() noexcept {
		TryRead();
	}

	/* virtual methods from class Istream */

	off_t _GetAvailable(bool partial) noexcept override;

	void _Read() noexcept override {
		retry_event.Cancel();
		TryRead();
	}

	int _AsFd() noexcept override;
	void _Close() noexcept override {
		Destroy();
	}
};

inline void
FdIstream::TryData() noexcept
{
	if (buffer.IsNull()) {
		buffer.Allocate(fb_pool_get());
	} else {
		const size_t available = buffer.GetAvailable();
		if (available > 0) {
			if (SendFromBuffer(buffer) == 0)
				/* not a single byte was consumed: we may have been
				   closed, and we must bail out now */
				return;
		}
	}

	ssize_t nbytes = read_to_buffer(fd.Get(), buffer, INT_MAX);
	if (nbytes == 0) {
		fd.Close();
		if (buffer.empty())
			DestroyEof();
		return;
	} else if (nbytes == -1) {
		DestroyError(std::make_exception_ptr(FormatErrno("Failed to read from '%s'",
								 path)));
		return;
	}

	assert(!buffer.empty());

	SendFromBuffer(buffer);
}

inline void
FdIstream::TryDirect() noexcept
{
	/* first consume the rest of the buffer */
	if (ConsumeFromBuffer(buffer) > 0)
		return;

	ssize_t nbytes = InvokeDirect(fd_type, fd.Get(), INT_MAX);
	if (nbytes == ISTREAM_RESULT_CLOSED)
		/* this stream was closed during the direct() callback */
		return;

	if (nbytes > 0 || nbytes == ISTREAM_RESULT_BLOCKING) {
	} else if (nbytes == ISTREAM_RESULT_EOF) {
		DestroyEof();
	} else if (errno == EAGAIN) {
		/* this should only happen for splice(SPLICE_F_NONBLOCK) from
		   NFS files - unfortunately we cannot use SocketEvent::READ
		   here, so we just install a timer which retries after
		   100ms */

		retry_event.Schedule(file_retry_timeout);
	} else {
		/* XXX */
		DestroyError(std::make_exception_ptr(FormatErrno("Failed to read from '%s'",
								 path)));
	}
}

/*
 * istream implementation
 *
 */

off_t
FdIstream::_GetAvailable(bool partial) noexcept
{
	return partial
		? buffer.GetAvailable()
		: -1;
}

int
FdIstream::_AsFd() noexcept
{
	if (!fd.IsDefined())
		return -1;

	int result_fd = fd.Steal();
	Destroy();
	return result_fd;
}

/*
 * constructor and public methods
 *
 */

UnusedIstreamPtr
NewFdIstream(EventLoop &event_loop, struct pool &pool,
	     const char *path,
	     UniqueFileDescriptor fd, FdType fd_type) noexcept
{
	assert(fd.IsDefined());

	return NewIstreamPtr<FdIstream>(pool, event_loop,
					std::move(fd), fd_type, path);
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "DriverAccess.h"
#include "Public.h"

//------------------------------------------------------------------------------------------------

UsbDkDriverAccess::UsbDkDriverAccess()
{
    m_hDriver = CreateFile(USBDK_USERMODE_NAME,
                           GENERIC_READ | GENERIC_WRITE,
                           0,
                           NULL,
                           CREATE_ALWAYS,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);

    if (m_hDriver == INVALID_HANDLE_VALUE)
    {
        throw UsbDkDriverAccessException(TEXT("Failed to open device symlink"));
    }
}
//------------------------------------------------------------------------------------------------

UsbDkDriverAccess::~UsbDkDriverAccess()
{
    CloseHandle(m_hDriver);
}
//------------------------------------------------------------------------------------------------

void UsbDkDriverAccess::GetDevicesList(PUSB_DK_DEVICE_ID &DevicesArray, ULONG &NumberDevice)
{
    DevicesArray = nullptr;
    for (;;)
    {
        DWORD   bytesReturned;

        // get number of devices
        if (!DeviceIoControl(m_hDriver,
            IOCTL_USBDK_COUNT_DEVICES,
            nullptr,
            0,
            &NumberDevice,
            sizeof(NumberDevice),
            &bytesReturned,
            nullptr))
        {
            throw UsbDkDriverAccessException(TEXT("Counting devices failed"));
        }

        // get list of devices
        delete DevicesArray;
        DevicesArray = new USB_DK_DEVICE_ID[NumberDevice];

        if (!DeviceIoControl(m_hDriver,
            IOCTL_USBDK_ENUM_DEVICES,
            nullptr,
            0,
            DevicesArray,
            NumberDevice * sizeof(USB_DK_DEVICE_ID),
            &bytesReturned,
            nullptr))
        {
            DWORD err = GetLastError();
            if (err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_MORE_DATA)
            {
                continue;
            }
            else
            {
                UsbDkDriverAccessException(TEXT("Enumiration devices failed in DeviceIoControl."), err);
            }
        }
        break;
    }
}
//------------------------------------------------------------------------------------------------
void UsbDkDriverAccess::ReleaseDeviceList(PUSB_DK_DEVICE_ID DevicesArray)
{
    delete[] DevicesArray;
}
//------------------------------------------------------------------------------------------------

void UsbDkDriverAccess::ResetDevice(USB_DK_DEVICE_ID &DeviceID)
{
    SendIoctlWithDeviceId(IOCTL_USBDK_RESET_DEVICE, DeviceID);
}
//------------------------------------------------------------------------------------------------

void UsbDkDriverAccess::AddRedirect(USB_DK_DEVICE_ID &DeviceID)
{
    SendIoctlWithDeviceId(IOCTL_USBDK_ADD_REDIRECT, DeviceID);
}
//------------------------------------------------------------------------------------------------

void UsbDkDriverAccess::RemoveRedirect(USB_DK_DEVICE_ID &DeviceID)
{
    SendIoctlWithDeviceId(IOCTL_USBDK_REMOVE_REDIRECT, DeviceID);
}
//------------------------------------------------------------------------------------------------

void UsbDkDriverAccess::SendIoctlWithDeviceId(DWORD ControlCode,
                                              USB_DK_DEVICE_ID &Id)
{
    DWORD   bytesReturned;
    if (!DeviceIoControl(m_hDriver, ControlCode, &Id, sizeof(Id),
                         nullptr, 0, &bytesReturned, nullptr))
    {
        throw UsbDkDriverAccessException(TEXT("Ioctl failed"));
    }
}
<commit_msg>UsbDkHelper: Fix devices number on enumeration<commit_after>#include "stdafx.h"
#include "DriverAccess.h"
#include "Public.h"

//------------------------------------------------------------------------------------------------

UsbDkDriverAccess::UsbDkDriverAccess()
{
    m_hDriver = CreateFile(USBDK_USERMODE_NAME,
                           GENERIC_READ | GENERIC_WRITE,
                           0,
                           NULL,
                           CREATE_ALWAYS,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);

    if (m_hDriver == INVALID_HANDLE_VALUE)
    {
        throw UsbDkDriverAccessException(TEXT("Failed to open device symlink"));
    }
}
//------------------------------------------------------------------------------------------------

UsbDkDriverAccess::~UsbDkDriverAccess()
{
    CloseHandle(m_hDriver);
}
//------------------------------------------------------------------------------------------------

void UsbDkDriverAccess::GetDevicesList(PUSB_DK_DEVICE_ID &DevicesArray, ULONG &NumberDevice)
{
    DevicesArray = nullptr;
    for (;;)
    {
        DWORD   bytesReturned;

        // get number of devices
        if (!DeviceIoControl(m_hDriver,
            IOCTL_USBDK_COUNT_DEVICES,
            nullptr,
            0,
            &NumberDevice,
            sizeof(NumberDevice),
            &bytesReturned,
            nullptr))
        {
            throw UsbDkDriverAccessException(TEXT("Counting devices failed"));
        }

        // get list of devices
        delete DevicesArray;
        DevicesArray = new USB_DK_DEVICE_ID[NumberDevice];

        if (!DeviceIoControl(m_hDriver,
            IOCTL_USBDK_ENUM_DEVICES,
            nullptr,
            0,
            DevicesArray,
            NumberDevice * sizeof(USB_DK_DEVICE_ID),
            &bytesReturned,
            nullptr))
        {
            DWORD err = GetLastError();
            if (err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_MORE_DATA)
            {
                continue;
            }
            else
            {
                UsbDkDriverAccessException(TEXT("Enumiration devices failed in DeviceIoControl."), err);
            }
        }
        NumberDevice = bytesReturned / sizeof(USB_DK_DEVICE_ID);
        break;
    }
}
//------------------------------------------------------------------------------------------------
void UsbDkDriverAccess::ReleaseDeviceList(PUSB_DK_DEVICE_ID DevicesArray)
{
    delete[] DevicesArray;
}
//------------------------------------------------------------------------------------------------

void UsbDkDriverAccess::ResetDevice(USB_DK_DEVICE_ID &DeviceID)
{
    SendIoctlWithDeviceId(IOCTL_USBDK_RESET_DEVICE, DeviceID);
}
//------------------------------------------------------------------------------------------------

void UsbDkDriverAccess::AddRedirect(USB_DK_DEVICE_ID &DeviceID)
{
    SendIoctlWithDeviceId(IOCTL_USBDK_ADD_REDIRECT, DeviceID);
}
//------------------------------------------------------------------------------------------------

void UsbDkDriverAccess::RemoveRedirect(USB_DK_DEVICE_ID &DeviceID)
{
    SendIoctlWithDeviceId(IOCTL_USBDK_REMOVE_REDIRECT, DeviceID);
}
//------------------------------------------------------------------------------------------------

void UsbDkDriverAccess::SendIoctlWithDeviceId(DWORD ControlCode,
                                              USB_DK_DEVICE_ID &Id)
{
    DWORD   bytesReturned;
    if (!DeviceIoControl(m_hDriver, ControlCode, &Id, sizeof(Id),
                         nullptr, 0, &bytesReturned, nullptr))
    {
        throw UsbDkDriverAccessException(TEXT("Ioctl failed"));
    }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   KWSys - Kitware System Library
  Module:    testhash.cxx

  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(hash_map.hxx)
#include KWSYS_HEADER(hash_set.hxx)
#include KWSYS_HEADER(ios/iostream)

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
# include "hash_map.hxx.in"
# include "hash_set.hxx.in"
# include "kwsys_ios_iostream.h.in"
#endif

#if defined(_MSC_VER)
# pragma warning (disable:4786)
#endif

template class kwsys::hash_map<const char*, int>;
template class kwsys::hash_set<int>;

bool test_hash_map()
{
  typedef kwsys::hash_map<const char*, int> mtype;
  mtype m;
  const char* keys[] = {"hello", "world"};
  m[keys[0]] = 1;
  m.insert(mtype::value_type(keys[1], 2));
  int sum = 0;
  for(mtype::iterator mi = m.begin(); mi != m.end(); ++mi)
    {
    kwsys_ios::cout << "Found entry [" << mi->first << "," << mi->second << "]"
                    << kwsys_ios::endl;
    sum += mi->second;
    }
  return sum == 3;
}

bool test_hash_set()
{
  typedef kwsys::hash_set<int> stype;
  stype s;
  s.insert(1);
  s.insert(2);
  int sum = 0;
  for(stype::iterator si = s.begin(); si != s.end(); ++si)
    {
    kwsys_ios::cout << "Found entry [" << *si << "]" << kwsys_ios::endl;
    sum += *si;
    }
  return sum == 3;
}

int main()
{
  bool result = true;
  result = test_hash_map() && result;
  result = test_hash_set() && result;
  return result? 0:1;
}
<commit_msg>ENH: Added include-work-around for hashtable.hxx.in dependency.<commit_after>/*=========================================================================

  Program:   KWSys - Kitware System Library
  Module:    testhash.cxx

  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(hash_map.hxx)
#include KWSYS_HEADER(hash_set.hxx)
#include KWSYS_HEADER(ios/iostream)

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
# include "hash_map.hxx.in"
# include "hash_set.hxx.in"
# include "hashtable.hxx.in"
# include "kwsys_ios_iostream.h.in"
#endif

#if defined(_MSC_VER)
# pragma warning (disable:4786)
#endif

template class kwsys::hash_map<const char*, int>;
template class kwsys::hash_set<int>;

bool test_hash_map()
{
  typedef kwsys::hash_map<const char*, int> mtype;
  mtype m;
  const char* keys[] = {"hello", "world"};
  m[keys[0]] = 1;
  m.insert(mtype::value_type(keys[1], 2));
  int sum = 0;
  for(mtype::iterator mi = m.begin(); mi != m.end(); ++mi)
    {
    kwsys_ios::cout << "Found entry [" << mi->first << "," << mi->second << "]"
                    << kwsys_ios::endl;
    sum += mi->second;
    }
  return sum == 3;
}

bool test_hash_set()
{
  typedef kwsys::hash_set<int> stype;
  stype s;
  s.insert(1);
  s.insert(2);
  int sum = 0;
  for(stype::iterator si = s.begin(); si != s.end(); ++si)
    {
    kwsys_ios::cout << "Found entry [" << *si << "]" << kwsys_ios::endl;
    sum += *si;
    }
  return sum == 3;
}

int main()
{
  bool result = true;
  result = test_hash_map() && result;
  result = test_hash_set() && result;
  return result? 0:1;
}
<|endoftext|>


<commit_before>#include "project.h"
/**
 * @brief Project::Project
 * @param id
 * @param name
 */
Project::Project(ID id, std::string name)
{
    this->files = new ProjFiles();
    this->m_name = name;
    this->m_id = id;
    this->v_id = 0;
    this->videos.clear();
    this->saved = false;
}
/**
 * @brief Project::Project
 */
Project::Project(){
    this->files = new ProjFiles();
    this->m_name = "";
    this->m_id = -1;
    this->v_id = 0;
    this->videos.clear();
}
/**
 * @brief Project::~Project
 * Clears contents of video map
 */
Project::~Project(){
    for (auto vidIt = this->videos.begin(); vidIt != this->videos.end(); ++vidIt) {
        delete vidIt->second;
    }
}

/**
 * @brief Project::remove_video
 * @param id
 */
void Project::remove_video(ID id){
    Video* temp = this->videos.at(id);
    delete temp;
    videos.erase(id);

}

/**
 * @brief Project::add_video
 * @return
 */
ID Project::add_video(Video* vid){
    vid->id = this->v_id;
    this->videos.insert(std::make_pair(this->v_id, vid));
    return this->v_id++;
}

/**
 *  UNSFINISHED
 * @brief operator >>
 * @param is
 * @param proj
 * @return stringstream containing project information
 */
ProjectStream& operator>>(ProjectStream& ps, Project& proj){
    //write files
    //Read project id and name
    ps.projFile >> proj.m_name;

    // read videos
    int vidCounter = 0;
    std::vector<Video*> temp; // used to preserve order ov videos, important for == operator
    ps.videos >> vidCounter;
    if( vidCounter < 0) return ps; // if negative number of videos, loop below will
                                   // be infinite. This is unlikely to happen. but just in case!
    while(vidCounter--){
        Video* v = new Video();
        ps.videos >> *v;
        temp.push_back(v);
    }
    for (auto vidIt = temp.rbegin(); vidIt != temp.rend(); ++vidIt) {  // to preserve order we add videos in reverse
        proj.add_video(*vidIt);
    }
    return ps;
}
/**
 * @brief operator <<
 * @param os
 * @param proj
 * @return stream
 * used for writing videos to file
 */
ProjectStream& operator<<(ProjectStream &ps, const Project& proj){
    //write name and id;
    ps.projFile << proj.m_name.c_str() << " ";
    //write videos
    int vidcounter = proj.videos.size();
    ps.videos << vidcounter << " ";
    for(auto vid = proj.videos.rbegin(); vid != proj.videos.rend(); ++vid){
        Video* v = vid->second;
        if(v != nullptr){
            ps.videos << *v << " ";
            vidcounter++;
        }
    }
    return ps;
}

/**
 * @brief operator <<
 * @param ps
 * @param pf
 * @return ps
 * Writes a projectfile object to projectstream
 * @deprecated
 * Shouldnt be needed, ids useless and filenames are standard.
 * isnt currently used but works as intended.
 * kept just in case.
 */
ProjectStream& operator<<(ProjectStream &ps,const ProjFiles& pf){
    ps.projFile << pf.f_analysis << " ";
    ps.projFile << pf.f_drawings << " ";
    ps.projFile << pf.f_videos << " ";
    return ps;

}

/**
 * @brief operator >>
 * @param ps
 * @param pf
 * @return ps
 * Reads files from a ProjFiles struct to a ProjectStream
 * Shouldnt be needed, ids useless and filenames are standard.
 * isnt currently used but works as intended.
 * kept just in case.
 */
ProjectStream& operator>>(ProjectStream &ps, ProjFiles& pf){
    std::string dummy;
    ps.projFile >> pf.f_analysis;
    ps.projFile >> pf.f_drawings;
    ps.projFile >> pf.f_videos;
    return ps;
}
<commit_msg>added a couple of comments for remove video and add video<commit_after>#include "project.h"
/**
 * @brief Project::Project
 * @param id
 * @param name
 */
Project::Project(ID id, std::string name)
{
    this->files = new ProjFiles();
    this->m_name = name;
    this->m_id = id;
    this->v_id = 0;
    this->videos.clear();
    this->saved = false;
}
/**
 * @brief Project::Project
 */
Project::Project(){
    this->files = new ProjFiles();
    this->m_name = "";
    this->m_id = -1;
    this->v_id = 0;
    this->videos.clear();
}
/**
 * @brief Project::~Project
 * Clears contents of video map
 */
Project::~Project(){
    for (auto vidIt = this->videos.begin(); vidIt != this->videos.end(); ++vidIt) {
        delete vidIt->second;
    }
}

/**
 * @brief Project::remove_video
 * @param id
 * Remove video from videos and delete its contents.
 */
void Project::remove_video(ID id){
    Video* temp = this->videos.at(id);
    delete temp;
    videos.erase(id);

}

/**
 * @brief Project::add_video
 * @return Video ID to be used for identifying the video
 */
ID Project::add_video(Video* vid){
    vid->id = this->v_id;
    this->videos.insert(std::make_pair(this->v_id, vid));
    return this->v_id++;
}

/**
 *  UNSFINISHED
 * @brief operator >>
 * @param is
 * @param proj
 * @return stringstream containing project information
 */
ProjectStream& operator>>(ProjectStream& ps, Project& proj){
    //write files
    //Read project id and name
    ps.projFile >> proj.m_name;

    // read videos
    int vidCounter = 0;
    std::vector<Video*> temp; // used to preserve order ov videos, important for == operator
    ps.videos >> vidCounter;
    if( vidCounter < 0) return ps; // if negative number of videos, loop below will
                                   // be infinite. This is unlikely to happen. but just in case!
    while(vidCounter--){
        Video* v = new Video();
        ps.videos >> *v;
        temp.push_back(v);
    }
    for (auto vidIt = temp.rbegin(); vidIt != temp.rend(); ++vidIt) {  // to preserve order we add videos in reverse
        proj.add_video(*vidIt);
    }
    return ps;
}
/**
 * @brief operator <<
 * @param os
 * @param proj
 * @return stream
 * used for writing videos to file
 */
ProjectStream& operator<<(ProjectStream &ps, const Project& proj){
    //write name and id;
    ps.projFile << proj.m_name.c_str() << " ";
    //write videos
    int vidcounter = proj.videos.size();
    ps.videos << vidcounter << " ";
    for(auto vid = proj.videos.rbegin(); vid != proj.videos.rend(); ++vid){
        Video* v = vid->second;
        if(v != nullptr){
            ps.videos << *v << " ";
            vidcounter++;
        }
    }
    return ps;
}

/**
 * @brief operator <<
 * @param ps
 * @param pf
 * @return ps
 * Writes a projectfile object to projectstream
 * @deprecated
 * Shouldnt be needed, ids useless and filenames are standard.
 * isnt currently used but works as intended.
 * kept just in case.
 */
ProjectStream& operator<<(ProjectStream &ps,const ProjFiles& pf){
    ps.projFile << pf.f_analysis << " ";
    ps.projFile << pf.f_drawings << " ";
    ps.projFile << pf.f_videos << " ";
    return ps;

}

/**
 * @brief operator >>
 * @param ps
 * @param pf
 * @return ps
 * Reads files from a ProjFiles struct to a ProjectStream
 * Shouldnt be needed, ids useless and filenames are standard.
 * isnt currently used but works as intended.
 * kept just in case.
 */
ProjectStream& operator>>(ProjectStream &ps, ProjFiles& pf){
    std::string dummy;
    ps.projFile >> pf.f_analysis;
    ps.projFile >> pf.f_drawings;
    ps.projFile >> pf.f_videos;
    return ps;
}
<|endoftext|>


<commit_before>#include "apfBox.h"

#include "apfMDS.h"
#include <gmi_lookup.h>
#include <cassert>
#include <cstdlib>

namespace apf {

Indices::Indices() {}

Indices::Indices(int a, int b, int c): x(a),y(b),z(c) {}

int& Indices::operator[](int i)
{
  switch (i) {
    case 0: return x;
    case 1: return y;
    case 2: return z;
    default: printf("i must be in {0,1,2}"); abort(); return x;
  }
}

Indices Indices::operator+(Indices oi)
{
  return Indices(x + oi.x, y + oi.y, z + oi.z);
}

Indices Indices::operator*(int s)
{
  return Indices(x * s, y * s, z * s);
}

Indices Indices::unit(int d)
{
  Indices i(0,0,0);
  i[d] = 1;
  return i;
}

Grid::Grid(int nx, int ny, int nz):
  size(nx, ny, nz)
{
  stride[0] = 1;
  for (int i = 0; i < 3; ++i)
    stride[i + 1] = stride[i] * size[i];
}

int Grid::total() {return stride[3];}

Indices Grid::out(int i)
{
  Indices is;
  for (int j = 0; j < 3; ++j)
    is[j] = (i % stride[j + 1]) / stride[j];
  return is;
}

int Grid::in(Indices is)
{
  int i = 0;
  for (int j = 0; j < 3; ++j)
    i += is[j] * stride[j];
  return i;
}

BoxBuilder::BoxBuilder(int nx, int ny, int nz,
      double wx, double wy, double wz,
      bool is):
  grid(nx + 1, ny + 1, nz + 1),
  mgrid(nx ? 3 : 1, ny ? 3 : 1, nz ? 3 : 1)
{
  for (dim = 0; dim < 3 && grid.size[dim] > 1; ++dim);
  w[0] = nx ? (wx / nx) : 0;
  w[1] = ny ? (wy / ny) : 0;
  w[2] = nz ? (wz / nz) : 0;
  is_simplex = is;
  formModelTable();
  gmi_model* gm = buildModel();
  m = makeEmptyMdsMesh(gm, dim, false);
  v.resize(grid.total());
  buildMeshAndModel();
}

void BoxBuilder::formModelTable()
{
  int nd[4] = {0,0,0,0};
  for (int i = 0; i < mgrid.total(); ++i) {
    Indices mi = mgrid.out(i);
    int mdim = 0;
    for (int j = 0; j < 3; ++j)
      if (mi[j] == 1)
        ++mdim;
    modelTable[i].dim = mdim;
    modelTable[i].tag = nd[mdim]++;
  }
  for (int i = 0; i < 4; ++i)
    modelCounts[i] = nd[i];
}

int BoxBuilder::getModelIndex(int i, int d)
{
  if (i == 0)
    return 0;
  if (i == grid.size[d] - 1)
    return 2;
  return 1;
}

Indices BoxBuilder::getModelIndices(Indices vi)
{
  Indices mi;
  for (int i = 0; i < 3; ++i)
    mi[i] = getModelIndex(vi[i], i);
  return mi;
}

ModelEntity* BoxBuilder::getModelEntity(Indices mi)
{
  int mj = mgrid.in(mi);
  int mdim = modelTable[mj].dim;
  int mtag = modelTable[mj].tag;
  return m->findModelEntity(mdim, mtag);
}

void BoxBuilder::addModelUse(gmi_base* gb, agm_bdry ab, Indices di)
{
  int ddim = modelTable[mgrid.in(di)].dim;
  int dtag = modelTable[mgrid.in(di)].tag;
  agm_ent ad = gmi_look_up(gb->lookup, agm_type_from_dim(ddim), dtag);
  agm_add_use(gb->topo, ab, ad);
}

gmi_model* BoxBuilder::buildModel()
{
  /* plain malloc because gmi_destroy calls plain free */
  gmi_base* gb = (gmi_base*) malloc(sizeof(*gb));
  gb->model.ops = &gmi_base_ops;
  gmi_base_init(gb);
  agm_ent_type at;
  agm_ent ae;
  agm_bdry ab;
  Indices di;
  for (int i = 0; i < mgrid.total(); ++i) {
    int mdim = modelTable[i].dim;
    int mtag = modelTable[i].tag;
    at = agm_type_from_dim(mdim);
    ae = agm_add_ent(gb->topo, at);
    gmi_set_lookup(gb->lookup, ae, mtag);
  }
  for (int i = 0; i < 4; ++i) {
    at = agm_type_from_dim(i);
    gmi_freeze_lookup(gb->lookup, at);
    gb->model.n[i] = agm_ent_count(gb->topo, at);
    assert(gb->model.n[i] == modelCounts[i]);
  }
  for (int i = 0; i < mgrid.total(); ++i) {
    int mdim = modelTable[i].dim;
    int mtag = modelTable[i].tag;
    if (mdim == 0)
      continue;
    at = agm_type_from_dim(mdim);
    ae = gmi_look_up(gb->lookup, at, mtag);
    Indices mi = mgrid.out(i);
    ab = agm_add_bdry(gb->topo, ae);
    for (int j = 0; j < 3; ++j)
      if (mi[j] == 1) {
        di = mi;
        di[j] = 0;
        addModelUse(gb, ab, di);
        di[j] = 2;
        addModelUse(gb, ab, di);
      }
  }
  return &gb->model;
}

void BoxBuilder::buildCellVert(int i)
{
  Indices vi = grid.out(i);
  v[i] = m->createVert(getModelEntity(getModelIndices(vi)));
  Vector3 pt(w[0] * vi.x, w[1] * vi.y, w[2] * vi.z);
  m->setPoint(v[i], 0, pt);
}

MeshEntity* BoxBuilder::getVert(Indices vi)
{
  return v.at(grid.in(vi));
}

void BoxBuilder::buildCellEdges(int i)
{
  Indices vi = grid.out(i);
  Indices mi = getModelIndices(vi);
  MeshEntity* ev[2];
  ev[0] = getVert(vi);
  for (int j = 0; j < 3; ++j) {
    if (mi[j] == mgrid.size[j] - 1)
      continue;
    ev[1] = getVert(vi + Indices::unit(j));
    Indices emi = mi;
    emi[j] = 1;
    ModelEntity* me = getModelEntity(emi);
    buildElement(m, me, Mesh::EDGE, ev);
  }
}

void BoxBuilder::buildTriangles(MeshEntity* fv[4], ModelEntity* me)
{
  MeshEntity* tv[3];
  tv[0] = fv[0]; tv[1] = fv[1]; tv[2] = fv[2];
  buildElement(m, me, Mesh::TRIANGLE, tv);
  tv[0] = fv[2]; tv[1] = fv[3]; tv[2] = fv[0];
  buildElement(m, me, Mesh::TRIANGLE, tv);
}

void BoxBuilder::buildFace(MeshEntity* fv[4], ModelEntity* me)
{
  if (is_simplex)
    buildTriangles(fv, me);
  else
    buildElement(m, me, Mesh::QUAD, fv);
}

void BoxBuilder::buildCellFaces(int i)
{
  Indices vi = grid.out(i);
  Indices mi = getModelIndices(vi);
  MeshEntity* fv[4];
  fv[0] = getVert(vi);
  for (int jx = 0; jx < 3; ++jx) {
    int jy = (jx + 1) % 3;
    if (mi[jx] == mgrid.size[jx] - 1 ||
        mi[jy] == mgrid.size[jy] - 1)
      continue;
    fv[1] = getVert(vi + Indices::unit(jx));
    fv[2] = getVert(vi + Indices::unit(jx) + Indices::unit(jy));
    fv[3] = getVert(vi + Indices::unit(jy));
    Indices emi = mi;
    emi[jx] = 1;
    emi[jy] = 1;
    ModelEntity* me = getModelEntity(emi);
    buildFace(fv, me);
  }
}

void BoxBuilder::buildTets(MeshEntity* rv[8], ModelEntity* me)
{
  static int const tet_verts[6][4] = {
  {0,1,2,6},
  {0,2,3,6},
  {0,3,7,6},
  {0,7,4,6},
  {0,4,5,6},
  {0,5,1,6}};
  for (int i = 0; i < 6; ++i) {
    MeshEntity* tv[4];
    for (int j = 0; j < 4; ++j)
      tv[j] = rv[tet_verts[i][j]];
    buildElement(m, me, Mesh::TET, tv);
  }
}

void BoxBuilder::buildHex(MeshEntity* rv[8], ModelEntity* me)
{
  buildElement(m, me, Mesh::HEX, rv);
}

void BoxBuilder::buildRegion(MeshEntity* rv[8], ModelEntity* me)
{
  if (is_simplex)
    buildTets(rv, me);
  else
    buildHex(rv, me);
}

void BoxBuilder::buildCellRegion(int i)
{
  Indices vi = grid.out(i);
  Indices mi = getModelIndices(vi);
  if (mi.x == mgrid.size.x - 1 ||
      mi.y == mgrid.size.y - 1 ||
      mi.z == mgrid.size.z - 1)
    return;
  MeshEntity* rv[8];
  rv[0] = getVert(Indices(vi.x + 0, vi.y + 0, vi.z + 0));
  rv[1] = getVert(Indices(vi.x + 1, vi.y + 0, vi.z + 0));
  rv[2] = getVert(Indices(vi.x + 1, vi.y + 1, vi.z + 0));
  rv[3] = getVert(Indices(vi.x + 0, vi.y + 1, vi.z + 0));
  rv[4] = getVert(Indices(vi.x + 0, vi.y + 0, vi.z + 1));
  rv[5] = getVert(Indices(vi.x + 1, vi.y + 0, vi.z + 1));
  rv[6] = getVert(Indices(vi.x + 1, vi.y + 1, vi.z + 1));
  rv[7] = getVert(Indices(vi.x + 0, vi.y + 1, vi.z + 1));
  ModelEntity* me = getModelEntity(Indices(1,1,1));
  buildRegion(rv, me);
}

void BoxBuilder::buildCell(int i, int d)
{
  switch (d) {
    case 0:
      buildCellVert(i);
      return;
    case 1:
      buildCellEdges(i);
      return;
    case 2:
      buildCellFaces(i);
      return;
    case 3:
      buildCellRegion(i);
      return;
  };
}

void BoxBuilder::buildDimension(int d)
{
  for (int i = 0; i < grid.total(); ++i)
    buildCell(i, d);
}

void BoxBuilder::buildMeshAndModel()
{
  for (int d = 0; d <= dim; ++d)
    buildDimension(d);
  m->acceptChanges();
}

Mesh2* makeMdsBox(
    int nex, int ney, int nez,
    double wx, double wy, double wz, bool is)
{
  BoxBuilder bb(nex, ney, nez, wx, wy, wz, is);
  return bb.m;
}

}
<commit_msg>mds : silence one coverity warning<commit_after>#include "apfBox.h"

#include "apfMDS.h"
#include <gmi_lookup.h>
#include <cassert>
#include <cstdlib>

namespace apf {

Indices::Indices() : x(0), y(0), z(0) {}

Indices::Indices(int a, int b, int c): x(a),y(b),z(c) {}

int& Indices::operator[](int i)
{
  switch (i) {
    case 0: return x;
    case 1: return y;
    case 2: return z;
    default: printf("i must be in {0,1,2}"); abort(); return x;
  }
}

Indices Indices::operator+(Indices oi)
{
  return Indices(x + oi.x, y + oi.y, z + oi.z);
}

Indices Indices::operator*(int s)
{
  return Indices(x * s, y * s, z * s);
}

Indices Indices::unit(int d)
{
  Indices i(0,0,0);
  i[d] = 1;
  return i;
}

Grid::Grid(int nx, int ny, int nz):
  size(nx, ny, nz)
{
  stride[0] = 1;
  for (int i = 0; i < 3; ++i)
    stride[i + 1] = stride[i] * size[i];
}

int Grid::total() {return stride[3];}

Indices Grid::out(int i)
{
  Indices is;
  for (int j = 0; j < 3; ++j)
    is[j] = (i % stride[j + 1]) / stride[j];
  return is;
}

int Grid::in(Indices is)
{
  int i = 0;
  for (int j = 0; j < 3; ++j)
    i += is[j] * stride[j];
  return i;
}

BoxBuilder::BoxBuilder(int nx, int ny, int nz,
      double wx, double wy, double wz,
      bool is):
  grid(nx + 1, ny + 1, nz + 1),
  mgrid(nx ? 3 : 1, ny ? 3 : 1, nz ? 3 : 1)
{
  for (dim = 0; dim < 3 && grid.size[dim] > 1; ++dim);
  w[0] = nx ? (wx / nx) : 0;
  w[1] = ny ? (wy / ny) : 0;
  w[2] = nz ? (wz / nz) : 0;
  is_simplex = is;
  formModelTable();
  gmi_model* gm = buildModel();
  m = makeEmptyMdsMesh(gm, dim, false);
  v.resize(grid.total());
  buildMeshAndModel();
}

void BoxBuilder::formModelTable()
{
  int nd[4] = {0,0,0,0};
  for (int i = 0; i < mgrid.total(); ++i) {
    Indices mi = mgrid.out(i);
    int mdim = 0;
    for (int j = 0; j < 3; ++j)
      if (mi[j] == 1)
        ++mdim;
    modelTable[i].dim = mdim;
    modelTable[i].tag = nd[mdim]++;
  }
  for (int i = 0; i < 4; ++i)
    modelCounts[i] = nd[i];
}

int BoxBuilder::getModelIndex(int i, int d)
{
  if (i == 0)
    return 0;
  if (i == grid.size[d] - 1)
    return 2;
  return 1;
}

Indices BoxBuilder::getModelIndices(Indices vi)
{
  Indices mi;
  for (int i = 0; i < 3; ++i)
    mi[i] = getModelIndex(vi[i], i);
  return mi;
}

ModelEntity* BoxBuilder::getModelEntity(Indices mi)
{
  int mj = mgrid.in(mi);
  int mdim = modelTable[mj].dim;
  int mtag = modelTable[mj].tag;
  return m->findModelEntity(mdim, mtag);
}

void BoxBuilder::addModelUse(gmi_base* gb, agm_bdry ab, Indices di)
{
  int ddim = modelTable[mgrid.in(di)].dim;
  int dtag = modelTable[mgrid.in(di)].tag;
  agm_ent ad = gmi_look_up(gb->lookup, agm_type_from_dim(ddim), dtag);
  agm_add_use(gb->topo, ab, ad);
}

gmi_model* BoxBuilder::buildModel()
{
  /* plain malloc because gmi_destroy calls plain free */
  gmi_base* gb = (gmi_base*) malloc(sizeof(*gb));
  gb->model.ops = &gmi_base_ops;
  gmi_base_init(gb);
  agm_ent_type at;
  agm_ent ae;
  agm_bdry ab;
  Indices di;
  for (int i = 0; i < mgrid.total(); ++i) {
    int mdim = modelTable[i].dim;
    int mtag = modelTable[i].tag;
    at = agm_type_from_dim(mdim);
    ae = agm_add_ent(gb->topo, at);
    gmi_set_lookup(gb->lookup, ae, mtag);
  }
  for (int i = 0; i < 4; ++i) {
    at = agm_type_from_dim(i);
    gmi_freeze_lookup(gb->lookup, at);
    gb->model.n[i] = agm_ent_count(gb->topo, at);
    assert(gb->model.n[i] == modelCounts[i]);
  }
  for (int i = 0; i < mgrid.total(); ++i) {
    int mdim = modelTable[i].dim;
    int mtag = modelTable[i].tag;
    if (mdim == 0)
      continue;
    at = agm_type_from_dim(mdim);
    ae = gmi_look_up(gb->lookup, at, mtag);
    Indices mi = mgrid.out(i);
    ab = agm_add_bdry(gb->topo, ae);
    for (int j = 0; j < 3; ++j)
      if (mi[j] == 1) {
        di = mi;
        di[j] = 0;
        addModelUse(gb, ab, di);
        di[j] = 2;
        addModelUse(gb, ab, di);
      }
  }
  return &gb->model;
}

void BoxBuilder::buildCellVert(int i)
{
  Indices vi = grid.out(i);
  v[i] = m->createVert(getModelEntity(getModelIndices(vi)));
  Vector3 pt(w[0] * vi.x, w[1] * vi.y, w[2] * vi.z);
  m->setPoint(v[i], 0, pt);
}

MeshEntity* BoxBuilder::getVert(Indices vi)
{
  return v.at(grid.in(vi));
}

void BoxBuilder::buildCellEdges(int i)
{
  Indices vi = grid.out(i);
  Indices mi = getModelIndices(vi);
  MeshEntity* ev[2];
  ev[0] = getVert(vi);
  for (int j = 0; j < 3; ++j) {
    if (mi[j] == mgrid.size[j] - 1)
      continue;
    ev[1] = getVert(vi + Indices::unit(j));
    Indices emi = mi;
    emi[j] = 1;
    ModelEntity* me = getModelEntity(emi);
    buildElement(m, me, Mesh::EDGE, ev);
  }
}

void BoxBuilder::buildTriangles(MeshEntity* fv[4], ModelEntity* me)
{
  MeshEntity* tv[3];
  tv[0] = fv[0]; tv[1] = fv[1]; tv[2] = fv[2];
  buildElement(m, me, Mesh::TRIANGLE, tv);
  tv[0] = fv[2]; tv[1] = fv[3]; tv[2] = fv[0];
  buildElement(m, me, Mesh::TRIANGLE, tv);
}

void BoxBuilder::buildFace(MeshEntity* fv[4], ModelEntity* me)
{
  if (is_simplex)
    buildTriangles(fv, me);
  else
    buildElement(m, me, Mesh::QUAD, fv);
}

void BoxBuilder::buildCellFaces(int i)
{
  Indices vi = grid.out(i);
  Indices mi = getModelIndices(vi);
  MeshEntity* fv[4];
  fv[0] = getVert(vi);
  for (int jx = 0; jx < 3; ++jx) {
    int jy = (jx + 1) % 3;
    if (mi[jx] == mgrid.size[jx] - 1 ||
        mi[jy] == mgrid.size[jy] - 1)
      continue;
    fv[1] = getVert(vi + Indices::unit(jx));
    fv[2] = getVert(vi + Indices::unit(jx) + Indices::unit(jy));
    fv[3] = getVert(vi + Indices::unit(jy));
    Indices emi = mi;
    emi[jx] = 1;
    emi[jy] = 1;
    ModelEntity* me = getModelEntity(emi);
    buildFace(fv, me);
  }
}

void BoxBuilder::buildTets(MeshEntity* rv[8], ModelEntity* me)
{
  static int const tet_verts[6][4] = {
  {0,1,2,6},
  {0,2,3,6},
  {0,3,7,6},
  {0,7,4,6},
  {0,4,5,6},
  {0,5,1,6}};
  for (int i = 0; i < 6; ++i) {
    MeshEntity* tv[4];
    for (int j = 0; j < 4; ++j)
      tv[j] = rv[tet_verts[i][j]];
    buildElement(m, me, Mesh::TET, tv);
  }
}

void BoxBuilder::buildHex(MeshEntity* rv[8], ModelEntity* me)
{
  buildElement(m, me, Mesh::HEX, rv);
}

void BoxBuilder::buildRegion(MeshEntity* rv[8], ModelEntity* me)
{
  if (is_simplex)
    buildTets(rv, me);
  else
    buildHex(rv, me);
}

void BoxBuilder::buildCellRegion(int i)
{
  Indices vi = grid.out(i);
  Indices mi = getModelIndices(vi);
  if (mi.x == mgrid.size.x - 1 ||
      mi.y == mgrid.size.y - 1 ||
      mi.z == mgrid.size.z - 1)
    return;
  MeshEntity* rv[8];
  rv[0] = getVert(Indices(vi.x + 0, vi.y + 0, vi.z + 0));
  rv[1] = getVert(Indices(vi.x + 1, vi.y + 0, vi.z + 0));
  rv[2] = getVert(Indices(vi.x + 1, vi.y + 1, vi.z + 0));
  rv[3] = getVert(Indices(vi.x + 0, vi.y + 1, vi.z + 0));
  rv[4] = getVert(Indices(vi.x + 0, vi.y + 0, vi.z + 1));
  rv[5] = getVert(Indices(vi.x + 1, vi.y + 0, vi.z + 1));
  rv[6] = getVert(Indices(vi.x + 1, vi.y + 1, vi.z + 1));
  rv[7] = getVert(Indices(vi.x + 0, vi.y + 1, vi.z + 1));
  ModelEntity* me = getModelEntity(Indices(1,1,1));
  buildRegion(rv, me);
}

void BoxBuilder::buildCell(int i, int d)
{
  switch (d) {
    case 0:
      buildCellVert(i);
      return;
    case 1:
      buildCellEdges(i);
      return;
    case 2:
      buildCellFaces(i);
      return;
    case 3:
      buildCellRegion(i);
      return;
  };
}

void BoxBuilder::buildDimension(int d)
{
  for (int i = 0; i < grid.total(); ++i)
    buildCell(i, d);
}

void BoxBuilder::buildMeshAndModel()
{
  for (int d = 0; d <= dim; ++d)
    buildDimension(d);
  m->acceptChanges();
}

Mesh2* makeMdsBox(
    int nex, int ney, int nez,
    double wx, double wy, double wz, bool is)
{
  BoxBuilder bb(nex, ney, nez, wx, wy, wz, is);
  return bb.m;
}

}
<|endoftext|>


<commit_before>/*
* Copyright (c) 2014 Eran Pe'er.
*
* This program is made available under the terms of the MIT License.
*
* Created on Mar 10, 2014
*/

#include <string>

#include "tpunit++.hpp"
#include "fakeit.hpp"

using namespace fakeit;

struct DtorMocking : tpunit::TestFixture
{
	DtorMocking() :
		TestFixture(
		    TEST(DtorMocking::mock_virtual_dtor_with_fake), //
		    TEST(DtorMocking::mock_virtual_dtor_with_when),
            TEST(DtorMocking::mock_virtual_dtor_by_assignment),
            TEST(DtorMocking::call_dtor_without_delete),
            TEST(DtorMocking::spy_dtor),
			TEST(DtorMocking::production_takes_ownwership_with_uniqe_ptr)//
		)
	{
	}

	struct SomeInterface
	{
		virtual ~SomeInterface() = default;
	};

	void mock_virtual_dtor_with_fake() {
		Mock<SomeInterface> mock;
		Fake(Dtor(mock));
		SomeInterface * i = &(mock.get());
		delete i;
		delete i; // second delete should not throw exception
        Verify(Dtor(mock)).Twice();
	}

	void mock_virtual_dtor_with_when() {
		int a = 0;
		Mock<SomeInterface> mock;
		When(Dtor(mock)).Return().Do([&](){a++; });
		SomeInterface * i = &(mock.get());
        delete i; // do nothing
        delete i; // a++
        ASSERT_EQUAL(1, a);
	}

    void mock_virtual_dtor_by_assignment() {
        int a = 0;
        Mock<SomeInterface> mock;
        Dtor(mock) = [&](){a++; };
        SomeInterface * i = &(mock.get());
        delete i; // do nothing
        delete i; // a++
        ASSERT_EQUAL(2, a);
    }

	void production_takes_ownwership_with_uniqe_ptr() {
		Mock<SomeInterface> mock;
		Fake(Dtor(mock));
		SomeInterface * i = &mock.get();
		std::unique_ptr<SomeInterface> ptr(i);
	}

    void call_dtor_without_delete() {
        Mock<SomeInterface> mock;
        Fake(Dtor(mock));
        SomeInterface * i = &mock.get();
        i->~SomeInterface();
        Verify(Dtor(mock)).Once();
    }

    struct A {
        virtual ~A(){}
    };
    void spy_dtor() {
        A a;
        Mock<A> mock(a);
        Spy(Dtor(mock));
        A * i = &mock.get();
        delete i;
        Verify(Dtor(mock)).Once();
    }

} __DtorMocking;
<commit_msg>improve tests<commit_after>/*
* Copyright (c) 2014 Eran Pe'er.
*
* This program is made available under the terms of the MIT License.
*
* Created on Mar 10, 2014
*/

#include <string>

#include "tpunit++.hpp"
#include "fakeit.hpp"

using namespace fakeit;

struct DtorMocking : tpunit::TestFixture
{
	DtorMocking() :
		TestFixture(
		    TEST(DtorMocking::mock_virtual_dtor_with_fake), //
		    TEST(DtorMocking::mock_virtual_dtor_with_when),
            TEST(DtorMocking::mock_virtual_dtor_by_assignment),
            TEST(DtorMocking::call_dtor_without_delete),
            TEST(DtorMocking::spy_dtor),
			TEST(DtorMocking::production_takes_ownwership_with_uniqe_ptr)//
		)
	{
	}

	struct SomeInterface
	{
		virtual ~SomeInterface() = default;
	};

	void mock_virtual_dtor_with_fake() {
		Mock<SomeInterface> mock;
		Fake(Dtor(mock));
		SomeInterface * i = &(mock.get());
		delete i;
		delete i; // second delete should not throw exception
        Verify(Dtor(mock)).Twice();
		ASSERT_THROW(Verify(Dtor(mock)).Once(), fakeit::VerificationException);
	}

	void mock_virtual_dtor_with_when() {
		int a = 0;
		Mock<SomeInterface> mock;
		When(Dtor(mock)).Return().Do([&](){a++; });
		SomeInterface * i = &(mock.get());
        delete i; // do nothing
        delete i; // a++
        ASSERT_EQUAL(1, a);
	}

    void mock_virtual_dtor_by_assignment() {
        int a = 0;
        Mock<SomeInterface> mock;
        Dtor(mock) = [&](){a++; };
        SomeInterface * i = &(mock.get());
        delete i; // do nothing
        delete i; // a++
        ASSERT_EQUAL(2, a);
    }

	void production_takes_ownwership_with_uniqe_ptr() {
		Mock<SomeInterface> mock;
		Fake(Dtor(mock));
		SomeInterface * i = &mock.get();
		std::unique_ptr<SomeInterface> ptr(i);
	}

    void call_dtor_without_delete() {
        Mock<SomeInterface> mock;
        Fake(Dtor(mock));
        SomeInterface * i = &mock.get();
        i->~SomeInterface();
        Verify(Dtor(mock)).Once();
		ASSERT_THROW(Verify(Dtor(mock)).Twice(), fakeit::VerificationException);
	}

    struct A {
        virtual ~A(){}
    };

	void spy_dtor() {
        A a;
        Mock<A> mock(a);
        Spy(Dtor(mock));
        A * i = &mock.get();
        delete i;
        Verify(Dtor(mock)).Once();
		ASSERT_THROW(Verify(Dtor(mock)).Twice(), fakeit::VerificationException);
    }

} __DtorMocking;
<|endoftext|>


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

#include "easysetup.h"
#include "easysetup_wifi_conn.h"

#include <unistd.h>
#include <string.h>
#include <iostream>
#include <pthread.h>
#include <glib.h>
#include <limits>
#include <unistd.h>
#define TAG "TIZEN_ES"

using namespace std;

gboolean mainThread(GIOChannel *source, GIOCondition condition, gpointer data);
void *listeningFunc(void *);

GMainLoop *gMainloop;
static pthread_t gThreadHandle = 0;

/**
 * Secure Virtual Resource database for Iotivity Server
 * It contains Server's Identity and the PSK credentials
 * of other devices which the server trusts
 */
#ifdef MULTIPLE_OWNER
static char CRED_FILE[] = "oic_svr_db_server_MOT.dat";
#else
static char CRED_FILE[] = "oic_svr_db_server.dat";
#endif

OCPersistentStorage ps;

/**
 * @var gIsSecured
 * @brief Variable to check if secure mode is enabled or not.
 */
static bool gIsSecured = false;
static bool gWiFiCBflag = false;
static char gSSID[OIC_STRING_MAX_VALUE];
static char gPasswd[OIC_STRING_MAX_VALUE];

void PrintMenu()
{
    cout << "========================" << endl;
    cout << "A: Enabled Security" << endl;
    cout << "B: Init & Start EasySetup" << endl;
    cout << "C: Set DeviceInfo" << endl;
    cout << "D: Connect to TargetAP" << endl;
    cout << "E: Show Menu......." << endl;
    cout << "Q: Terminate" << endl;
    cout << "========================" << endl;
}

void ConnectRequestCbInApp(ESConnectRequest *connectRequest)
{
    cout << "ConnectRequestCbInApp IN" << endl;

    if(connectRequest == NULL)
    {
        cout << "connectRequest is NULL" << endl;
        return ;
    }

    for(int i = 0 ; i < connectRequest->numRequest ; ++i)
    {
        cout << "connect : " << connectRequest->connect[i] << endl;
    }

    cout << "ConnectRequestCbInApp OUT" << endl;
    PrintMenu();
}

void WiFiConfProvCbInApp(ESWiFiConfData *eventData)
{
    cout << "WiFiConfProvCbInApp IN" << endl;
    gWiFiCBflag = true;

    ESSetState(ES_STATE_CONNECTING_TO_ENROLLER);

    if(eventData == NULL)
    {
        cout << "ESWiFiConfData is NULL" << endl;
        return ;
    }

    cout << "SSID : " << eventData->ssid << endl;
    cout << "Password : " << eventData->pwd << endl;
    cout << "AuthType : " << eventData->authtype << endl;
    cout << "EncType : " << eventData->enctype << endl;

    memset(gSSID, 0, OIC_STRING_MAX_VALUE);
    memset(gPasswd, 0, OIC_STRING_MAX_VALUE);
    if(eventData->ssid != NULL)
    {
        strncpy(gSSID, eventData->ssid, strlen(eventData->ssid));
    }

    if(eventData->pwd != NULL)
    {
        strncpy(gPasswd, eventData->pwd, strlen(eventData->pwd));
    }

    cout << "WiFiConfProvCbInApp OUT" << endl;
    PrintMenu();
}

void DevConfProvCbInApp(ESDevConfData *eventData)
{
    cout << "DevConfProvCbInApp IN" << endl;

    if(eventData == NULL)
    {
        cout << "ESDevConfData is NULL" << endl;
        return ;
    }

    cout << "Language : " << eventData->language << endl;
    cout << "Country : " << eventData->country << endl;

    cout << "DevConfProvCbInApp OUT" << endl;
    PrintMenu();
}

void CoapCloudConfProvCbInApp(ESCoapCloudConfData *eventData)
{
    cout << "CoapCloudConfProvCbInApp IN" << endl;

    if(eventData == NULL)
    {
        cout << "ESCoapCloudConfData is NULL" << endl;
        return ;
    }

    cout << "AuthCode : " << eventData->authCode << endl;
    cout << "AcessToken : " <<  eventData->accessToken << endl;
    cout << "AcessTokenType : "<< eventData->accessTokenType << endl;
    cout << "AuthProvider : " << eventData->authProvider << endl;
    cout << "CI Server : " << eventData->ciServer << endl;

    cout << "CoapCloudConfProvCbInApp OUT" << endl;
    PrintMenu();
}

ESProvisioningCallbacks gCallbacks = {
    .ConnectRequestCb = &ConnectRequestCbInApp,
    .WiFiConfProvCb = &WiFiConfProvCbInApp,
    .DevConfProvCb = &DevConfProvCbInApp,
    .CoapCloudConfProvCb = &CoapCloudConfProvCbInApp
};

FILE* server_fopen(const char *path, const char *mode)
{
    if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
    {
        return fopen(CRED_FILE, mode);
    }
    else
    {
        return fopen(path, mode);
    }
}

void EnableSecurity()
{
    cout << "Inside EnableSecurity API.." << endl;

    gIsSecured = true;

    // Initialize Persistent Storage for SVR database
    ps = (OCPersistentStorage){ server_fopen, fread, fwrite, fclose, unlink };
    OCRegisterPersistentStorageHandler(&ps);
}

void StartEasySetup()
{
    cout << "StartEasySetup IN" << endl;

    if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
    {
        cout << "OCStack init error!!" << endl;
        return;
    }

    ESResourceMask resourcemMask = (ESResourceMask) (ES_WIFICONF_RESOURCE | ES_COAPCLOUDCONF_RESOURCE | ES_DEVCONF_RESOURCE);
    cout << "resourcemMask : " << resourcemMask << endl;
    if(ESInitEnrollee(gIsSecured, resourcemMask, gCallbacks) != ES_OK)
    {
        cout << "OCStack init error!!" << endl;
        return;
    }

    cout << "ESInitEnrollee Success" << endl;

    if(gThreadHandle == 0) {

        if (pthread_create(&gThreadHandle, NULL, listeningFunc, NULL)) {
            cout << "Thread creation failed" << endl;
            return;
        }

    }

    ESSetState(ES_STATE_INIT);
    ESSetErrorCode(ES_ERRCODE_NO_ERROR);

    int ret = 0;

    ret = TizenWiFiInit();
    if(ret != WIFI_NO_ERROR) {
        cout << "WiFi Init Error" << endl;
    }
    else
        cout << "WiFi Init Success" << endl;

    ret = TizenWiFiScanStart();
    if(ret != WIFI_NO_ERROR) {
        cout << "WiFi Scan Error" << endl;
    }
    else
        cout << "WiFi Scan Success" << endl;

    cout << "StartEasySetup OUT" << endl;
}

void SetDeviceInfo()
{
    cout << "SetDeviceInfo IN" << endl;

    ESDeviceProperty deviceProperty = {
        {{WIFI_11G, WIFI_11N, WIFI_11AC, WiFi_EOF}, WIFI_5G}, {"Tizen Device"}
    };

    // Set user properties if needed

    // Set device properties
    if(ESSetDeviceProperty(&deviceProperty) == ES_ERROR)
    {
        cout << "ESSetDeviceProperty Error" << endl;
    }

    cout << "SetDeviceInfo OUT" << endl;
}

void StopEasySetup()
{
    cout << "StopEasySetup IN" << endl;
    if (ESTerminateEnrollee() == ES_ERROR)
    {
        cout << "ESTerminateEnrollee Failed!!" << endl;
        return;
    }

    // Deinit Tizen Wifi
    TizenWiFiDeinit();

    // Stop OC Stack
    if (OCStop() != OC_STACK_OK)
    {
        cout << "OCStack stop failed!!" << endl;
        return;
    }

    if(gThreadHandle != 0) {
        pthread_cancel(gThreadHandle);
        pthread_join(gThreadHandle, NULL);
    }

    cout << "StopEasySetup OUT" << endl;
}

void ConnectToTargetAP()
{
    if(!gWiFiCBflag){
        cout << "WiFi Provisioning is needed to be preceded" << endl;
        return;
    }

    WiFiConnErrCode ret = WIFI_NO_ERROR;
    ret = TizenWiFiScanStart();
    if(ret != WIFI_NO_ERROR){
        ESSetState(ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER);
        ESSetErrorCode(ES_ERRCODE_UNKNOWN);
        cout << "WiFi Scan Error" << endl;
        return;
    }
    else{
        cout << "WiFi Scan Succss" << endl;
    }

    ret = TizenWiFiConn(gSSID, gPasswd);
    if(ret != WIFI_NO_ERROR) {
        ESSetState(ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER);

        if(ret == WIFI_NOTFOUND_SSID_ERROR) {
            ESSetErrorCode(ES_ERRCODE_SSID_NOT_FOUND);
        }
        else if(ret == WIFI_WRONG_PWD_ERROR) {
            ESSetErrorCode(ES_ERRCODE_PW_WRONG);
        }
        else {
            ESSetErrorCode(ES_ERRCODE_TIMEOUT);
        }
        cout << "WiFi Connection Error" << endl;
        return;
    }
    else {
        cout << "WIFI Connection Success" << endl;
        ESSetState(ES_STATE_CONNECTED_TO_ENROLLER);
        ESSetErrorCode(ES_ERRCODE_NO_ERROR);
    }
}

gboolean mainThread(GIOChannel *source, GIOCondition condition, gpointer data)
{
    char entered;
    cin >> entered;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    switch (entered) {
        case 'Q': // quit
        case 'q':
            StopEasySetup();
            break;

        case 'A': // Enable Security
        case 'a':
#ifdef __WITH_DTLS__
            EnableSecurity();
#else
            cout << "Sample is not built with secured mode" << endl;
#endif
            PrintMenu();
            break;

        case 'B': // Init EasySetup
        case 'b':
            StartEasySetup();
            PrintMenu();
            break;

        case 'C': // Set Device Info
        case 'c':
            SetDeviceInfo();
            PrintMenu();
            break;

        case 'D': // Start to connect target AP
        case 'd':
            ConnectToTargetAP();
            PrintMenu();
            break;

        case 'E': // Print Menu
        case 'e':
            PrintMenu();
            break;

        default:
            cout << "Wrong option" << endl;
            PrintMenu();
            break;
    }

    if(entered == 'q' || entered == 'Q'){
        g_main_loop_quit(gMainloop);
    }

    return TRUE;
}

int main()
{
    cout << "#########################" << endl;
    cout << "EasySetup Enrollee SAMPLE" << endl;
    cout << "#########################" << endl;
    PrintMenu();

    gMainloop = g_main_loop_new (NULL, FALSE);
    if(gMainloop == NULL) {
        cout << "Create Main Loop Error" << endl;
        return 0;
    }

    GIOChannel *channel = g_io_channel_unix_new(0);
    g_io_add_watch(channel, (GIOCondition)(G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL), mainThread, NULL);

    g_main_loop_run (gMainloop);

    cout << "#########################" << endl;
    cout << "Terminate Enrollee SAMPLE" << endl;
    cout << "#########################" << endl;

    return 0;
}

void *listeningFunc(void*)
{
    OCStackResult result;

    while (true)
    {
        result = OCProcess();
        if (result != OC_STACK_OK)
        {
           cout<<"OCStack stop error";
        }
    }
    return NULL;
}

<commit_msg>[IOT-2057] Tizen enrollee sample app fix.<commit_after>//******************************************************************
//
// Copyright 2016 Samsung Electronics All Rights Reserved.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

#include "easysetup.h"
#include "easysetup_wifi_conn.h"

#include <unistd.h>
#include <string.h>
#include <iostream>
#include <pthread.h>
#include <glib.h>
#include <limits>
#include <unistd.h>
#define TAG "TIZEN_ES"

using namespace std;

gboolean mainThread(GIOChannel *source, GIOCondition condition, gpointer data);
void *listeningFunc(void *);

GMainLoop *gMainloop;
static pthread_t gThreadHandle = 0;

/**
 * Secure Virtual Resource database for Iotivity Server
 * It contains Server's Identity and the PSK credentials
 * of other devices which the server trusts
 */
#ifdef MULTIPLE_OWNER
static char CRED_FILE[] = "oic_svr_db_server_MOT.dat";
#else
static char CRED_FILE[] = "oic_svr_db_server.dat";
#endif

OCPersistentStorage ps;

/**
 * @var gIsSecured
 * @brief Variable to check if secure mode is enabled or not.
 */
static bool gIsSecured = false;
static bool gWiFiCBflag = false;
static char gSSID[OIC_STRING_MAX_VALUE];
static char gPasswd[OIC_STRING_MAX_VALUE];

void PrintMenu()
{
    cout << "========================" << endl;
    cout << "A: Enabled Security" << endl;
    cout << "B: Init & Start EasySetup" << endl;
    cout << "C: Set DeviceInfo" << endl;
    cout << "D: Connect to TargetAP" << endl;
    cout << "E: Show Menu......." << endl;
    cout << "Q: Terminate" << endl;
    cout << "========================" << endl;
}

void ConnectRequestCbInApp(ESConnectRequest *connectRequest)
{
    cout << "ConnectRequestCbInApp IN" << endl;

    if(connectRequest == NULL)
    {
        cout << "connectRequest is NULL" << endl;
        return ;
    }

    for(int i = 0 ; i < connectRequest->numRequest ; ++i)
    {
        cout << "connect : " << connectRequest->connect[i] << endl;
    }

    cout << "ConnectRequestCbInApp OUT" << endl;
    PrintMenu();
}

void WiFiConfProvCbInApp(ESWiFiConfData *eventData)
{
    cout << "WiFiConfProvCbInApp IN" << endl;
    gWiFiCBflag = true;

    ESSetState(ES_STATE_CONNECTING_TO_ENROLLER);

    if(eventData == NULL)
    {
        cout << "ESWiFiConfData is NULL" << endl;
        return ;
    }

    cout << "SSID : " << eventData->ssid << endl;
    cout << "Password : " << eventData->pwd << endl;
    cout << "AuthType : " << eventData->authtype << endl;
    cout << "EncType : " << eventData->enctype << endl;

    memset(gSSID, 0, OIC_STRING_MAX_VALUE);
    memset(gPasswd, 0, OIC_STRING_MAX_VALUE);
    if(eventData->ssid != NULL)
    {
        strncpy(gSSID, eventData->ssid, strlen(eventData->ssid));
    }

    if(eventData->pwd != NULL)
    {
        strncpy(gPasswd, eventData->pwd, strlen(eventData->pwd));
    }

    cout << "WiFiConfProvCbInApp OUT" << endl;
    PrintMenu();
}

void DevConfProvCbInApp(ESDevConfData *eventData)
{
    cout << "DevConfProvCbInApp IN" << endl;

    if(eventData == NULL)
    {
        cout << "ESDevConfData is NULL" << endl;
        return ;
    }

    cout << "DevConfProvCbInApp OUT" << endl;
    PrintMenu();
}

void CoapCloudConfProvCbInApp(ESCoapCloudConfData *eventData)
{
    cout << "CoapCloudConfProvCbInApp IN" << endl;

    if(eventData == NULL)
    {
        cout << "ESCoapCloudConfData is NULL" << endl;
        return ;
    }

    cout << "AuthCode : " << eventData->authCode << endl;
    cout << "AcessToken : " <<  eventData->accessToken << endl;
    cout << "AcessTokenType : "<< eventData->accessTokenType << endl;
    cout << "AuthProvider : " << eventData->authProvider << endl;
    cout << "CI Server : " << eventData->ciServer << endl;

    cout << "CoapCloudConfProvCbInApp OUT" << endl;
    PrintMenu();
}

ESProvisioningCallbacks gCallbacks = {
    .ConnectRequestCb = &ConnectRequestCbInApp,
    .WiFiConfProvCb = &WiFiConfProvCbInApp,
    .DevConfProvCb = &DevConfProvCbInApp,
    .CoapCloudConfProvCb = &CoapCloudConfProvCbInApp
};

FILE* server_fopen(const char *path, const char *mode)
{
    if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
    {
        return fopen(CRED_FILE, mode);
    }
    else
    {
        return fopen(path, mode);
    }
}

void EnableSecurity()
{
    cout << "Inside EnableSecurity API.." << endl;

    gIsSecured = true;

    // Initialize Persistent Storage for SVR database
    ps = (OCPersistentStorage){ server_fopen, fread, fwrite, fclose, unlink };
    OCRegisterPersistentStorageHandler(&ps);
}

void StartEasySetup()
{
    cout << "StartEasySetup IN" << endl;

    if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
    {
        cout << "OCStack init error!!" << endl;
        return;
    }

    ESResourceMask resourcemMask = (ESResourceMask) (ES_WIFICONF_RESOURCE | ES_COAPCLOUDCONF_RESOURCE | ES_DEVCONF_RESOURCE);
    cout << "resourcemMask : " << resourcemMask << endl;
    if(ESInitEnrollee(gIsSecured, resourcemMask, gCallbacks) != ES_OK)
    {
        cout << "OCStack init error!!" << endl;
        return;
    }

    cout << "ESInitEnrollee Success" << endl;

    if(gThreadHandle == 0) {

        if (pthread_create(&gThreadHandle, NULL, listeningFunc, NULL)) {
            cout << "Thread creation failed" << endl;
            return;
        }

    }

    ESSetState(ES_STATE_INIT);
    ESSetErrorCode(ES_ERRCODE_NO_ERROR);

    int ret = 0;

    ret = TizenWiFiInit();
    if(ret != WIFI_NO_ERROR) {
        cout << "WiFi Init Error" << endl;
    }
    else
        cout << "WiFi Init Success" << endl;

    ret = TizenWiFiScanStart();
    if(ret != WIFI_NO_ERROR) {
        cout << "WiFi Scan Error" << endl;
    }
    else
        cout << "WiFi Scan Success" << endl;

    cout << "StartEasySetup OUT" << endl;
}

void SetDeviceInfo()
{
    cout << "SetDeviceInfo IN" << endl;

    ESDeviceProperty deviceProperty = {
        {{WIFI_11G, WIFI_11N, WIFI_11AC, WiFi_EOF}, WIFI_5G}, {"Tizen Device"}
    };

    // Set user properties if needed

    // Set device properties
    if(ESSetDeviceProperty(&deviceProperty) == ES_ERROR)
    {
        cout << "ESSetDeviceProperty Error" << endl;
    }

    cout << "SetDeviceInfo OUT" << endl;
}

void StopEasySetup()
{
    cout << "StopEasySetup IN" << endl;
    if (ESTerminateEnrollee() == ES_ERROR)
    {
        cout << "ESTerminateEnrollee Failed!!" << endl;
        return;
    }

    // Deinit Tizen Wifi
    TizenWiFiDeinit();

    // Stop OC Stack
    if (OCStop() != OC_STACK_OK)
    {
        cout << "OCStack stop failed!!" << endl;
        return;
    }

    if(gThreadHandle != 0) {
        pthread_cancel(gThreadHandle);
        pthread_join(gThreadHandle, NULL);
    }

    cout << "StopEasySetup OUT" << endl;
}

void ConnectToTargetAP()
{
    if(!gWiFiCBflag){
        cout << "WiFi Provisioning is needed to be preceded" << endl;
        return;
    }

    WiFiConnErrCode ret = WIFI_NO_ERROR;
    ret = TizenWiFiScanStart();
    if(ret != WIFI_NO_ERROR){
        ESSetState(ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER);
        ESSetErrorCode(ES_ERRCODE_UNKNOWN);
        cout << "WiFi Scan Error" << endl;
        return;
    }
    else{
        cout << "WiFi Scan Succss" << endl;
    }

    ret = TizenWiFiConn(gSSID, gPasswd);
    if(ret != WIFI_NO_ERROR) {
        ESSetState(ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER);

        if(ret == WIFI_NOTFOUND_SSID_ERROR) {
            ESSetErrorCode(ES_ERRCODE_SSID_NOT_FOUND);
        }
        else if(ret == WIFI_WRONG_PWD_ERROR) {
            ESSetErrorCode(ES_ERRCODE_PW_WRONG);
        }
        else {
            ESSetErrorCode(ES_ERRCODE_TIMEOUT);
        }
        cout << "WiFi Connection Error" << endl;
        return;
    }
    else {
        cout << "WIFI Connection Success" << endl;
        ESSetState(ES_STATE_CONNECTED_TO_ENROLLER);
        ESSetErrorCode(ES_ERRCODE_NO_ERROR);
    }
}

gboolean mainThread(GIOChannel *source, GIOCondition condition, gpointer data)
{
    char entered;
    cin >> entered;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    switch (entered) {
        case 'Q': // quit
        case 'q':
            StopEasySetup();
            break;

        case 'A': // Enable Security
        case 'a':
#ifdef __WITH_DTLS__
            EnableSecurity();
#else
            cout << "Sample is not built with secured mode" << endl;
#endif
            PrintMenu();
            break;

        case 'B': // Init EasySetup
        case 'b':
            StartEasySetup();
            PrintMenu();
            break;

        case 'C': // Set Device Info
        case 'c':
            SetDeviceInfo();
            PrintMenu();
            break;

        case 'D': // Start to connect target AP
        case 'd':
            ConnectToTargetAP();
            PrintMenu();
            break;

        case 'E': // Print Menu
        case 'e':
            PrintMenu();
            break;

        default:
            cout << "Wrong option" << endl;
            PrintMenu();
            break;
    }

    if(entered == 'q' || entered == 'Q'){
        g_main_loop_quit(gMainloop);
    }

    return TRUE;
}

int main()
{
    cout << "#########################" << endl;
    cout << "EasySetup Enrollee SAMPLE" << endl;
    cout << "#########################" << endl;
    PrintMenu();

    gMainloop = g_main_loop_new (NULL, FALSE);
    if(gMainloop == NULL) {
        cout << "Create Main Loop Error" << endl;
        return 0;
    }

    GIOChannel *channel = g_io_channel_unix_new(0);
    g_io_add_watch(channel, (GIOCondition)(G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL), mainThread, NULL);

    g_main_loop_run (gMainloop);

    cout << "#########################" << endl;
    cout << "Terminate Enrollee SAMPLE" << endl;
    cout << "#########################" << endl;

    return 0;
}

void *listeningFunc(void*)
{
    OCStackResult result;

    while (true)
    {
        result = OCProcess();
        if (result != OC_STACK_OK)
        {
           cout<<"OCStack stop error";
        }
    }
    return NULL;
}

<|endoftext|>


<commit_before>#ifndef EXPR_HPP
#define EXPR_HPP

#include <iostream>
#include <memory>
#include <string>
#include <array>
#include <vector>
#include <type_traits>
#include <cmath>

/**
 * Virtual super-class for expression tree
 *
 * All important types and functions for outside users are
 * defined here.
 */
class expr {
public:

	/* It might be beter to use policy class instead */
	using ptr_type = std::unique_ptr<expr>;
	using string_type = std::string;
	using eval_type = double;
	using valuation_type = std::vector<eval_type>;

	virtual ptr_type derive(const valuation_type::size_type& var) = 0;
	virtual ptr_type clone() = 0;
	virtual string_type to_string() = 0;
	virtual eval_type eval(const valuation_type& values) = 0;
};

/**
 * Type of expression tree.
 *
 * Tree is basically pointer. This helps to keep track of tree
 * ownership. When you have tree_type - you own pointer otherwise
 * when you have tree_type::element_type you do NOT own this tree.
 * So you shouldn't (musn't) explicitly delete it.
 *
 * The class satisfies the requirements of MoveConstructible and
 * MoveAssignable, but not the requirements of either
 * CopyConstructible or CopyAssignable.
 */
using tree_type = std::unique_ptr<expr>;

/**
 * Child (subtree) container.
 *
 * TODO : What is more appropriete polymorphic hierarchy?
 * +------+    +-------+    +----------+
 * | expr | <- | n_ary | <- | function |
 * +------+    +-------+    +----------+
 *
 *               OR
 *
 * +------+    +----------+
 * | expr | <- | function |
 * +------+    +----------+
 *              /
 * +-------+   /
 * | n_ary | <-
 * +-------+
 */
template <std::size_t Arity>
class n_ary : public expr {
protected:
	std::array<expr::ptr_type, Arity> childs;

    template <class T, class U> friend class function;
};

/**
 * Every function type must be derived from this class
 */
struct function_base { };

struct variable : public function_base {
	constexpr static std::size_t arity = 0;
    typedef expr::valuation_type::size_type value_type;
	value_type var_num;
};

struct constant : public function_base {
	constexpr static std::size_t arity = 0;
    typedef expr::eval_type value_type;
	value_type c;
};

struct sin : public function_base { constexpr static std::size_t arity = 1; };
struct cos : public function_base { constexpr static std::size_t arity = 1; };
struct tan : public function_base { constexpr static std::size_t arity = 1; };
struct log : public function_base { constexpr static std::size_t arity = 1; };

struct add : public function_base { constexpr static std::size_t arity = 2; };
struct sub : public function_base { constexpr static std::size_t arity = 2; };
struct mul : public function_base { constexpr static std::size_t arity = 2; };
struct div : public function_base { constexpr static std::size_t arity = 2; };
struct pow : public function_base { constexpr static std::size_t arity = 2; };

/**
 * Compile time type property deduction
 * Specialisation for specific templates should be sufficient but this is
 * more elegant and general
 */
template <typename T>
class has_value {
    typedef char yes[1];
    typedef char no[2];

    template <typename U>
    static yes& test(typename U::value_type*);
    template <typename U>
    static no& test(...);

public:
    enum { value = (sizeof(yes) == sizeof(test<T>(0))) };
};

/**
 * Function class with all functionality
 *
 * Template parameter must be derived from function_base class - this makes
 * more human-readable compiler errors when invalid template parameter is
 * supplied.
 *
 * TODO : Conditionally derive from n_ary only when T::arity != 0
 */
template <class T, class Enable = void>
class function;

template <class T>
class function<
    T,
    typename std::enable_if<
        std::is_base_of<
            function_base,
            T
        >::value
    >::type
>
  : public T, public n_ary<T::arity> {
public:
	/**
	 * Constructor for functions with internal value
	 * Defined only for functions with value_type type
	 *
	 * TODO : Is possible to simply pass more then one parameter
	 *        without additional encapsulation (pair, tuple, vector, ...)?
	 * TODO : define template <class T> function<T>::operator std::string();
	 */
	template <
            typename U = T,
            typename std::enable_if<
                    has_value<U>::value
                >::type ...
        >
	function(const typename U::value_type& value);

    function() {};
    explicit function(const function<T>&) { };

	virtual expr::ptr_type derive(const expr::valuation_type::size_type& var);

	virtual expr::ptr_type clone() {
		return expr::ptr_type(new function<T>(*this));
	};

	virtual expr::string_type to_string();
	virtual expr::eval_type eval(const expr::valuation_type& values);

};

template <
        class T,
        class = typename std::enable_if<
                std::is_base_of<
                        function_base,
                        T
                    >::value
            >::type
    >
expr::ptr_type construct(typename T::value_type v) {
	return expr::ptr_type(nullptr);
}

/**
 * Required prototypes
 */
//template <> template <>
//inline function<constant>::function(const constant::value_type& val);

//template <> template <>
//inline function<variable>::function(const variable::value_type& val);

/*******************************************************
 ***** function<variable> template specialisations *****
 *******************************************************/

template <> template <>
inline function<variable>::function(const variable::value_type& vnum)
{ variable::var_num = vnum; }

template <>
inline expr::ptr_type function<variable>::derive(
    const expr::valuation_type::size_type& n)
{ return ptr_type(new function<constant>(n == var_num ? 1 : 0)); }

template <> inline expr::string_type function<variable>::to_string()
{ return "x_" + std::to_string(variable::var_num); }

template <>
inline expr::eval_type function<variable>::eval(
    const expr::valuation_type& values)
{ return values[variable::var_num]; }

/*******************************************************
 ***** function<constant> template specialisations *****
 *******************************************************/

template <> template <>
inline function<constant>::function(const constant::value_type& val)
{ constant::c = val; }

template <>
inline expr::ptr_type function<constant>::derive(
    const expr::valuation_type::size_type&)
{ return ptr_type(new function<constant>(0)); }

template <> inline expr::string_type function<constant>::to_string()
{ return std::to_string(constant::c); }

template <>
inline expr::eval_type function<constant>::eval(const expr::valuation_type&)
{ return constant::c; }

/*******************************************************
 *****   function<sin> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<struct sin>::derive(
        const expr::valuation_type::size_type& var) {
    auto *p = new function<struct cos>;
    p->childs[0] = std::move(n_ary::childs[0]->clone());
    return ptr_type(p);
}

template <> inline expr::string_type function<struct sin>::to_string()
{ return "sin(" + n_ary::childs[0]->to_string() + ")"; }

template <>
inline expr::eval_type function<struct sin>::eval(
        const expr::valuation_type& val)
{ return std::sin(n_ary::childs[0]->eval(val)); }

/*******************************************************
 *****   function<cos> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<struct cos>::derive(
        const expr::valuation_type::size_type& var) {
    auto *s = new function<struct sin>;
    s->childs[0] = std::move(n_ary::childs[0]->clone());
    auto *p = new function<mul>;
    p->childs[0] = std::move(ptr_type(s));
    p->childs[1] = std::move(n_ary::childs[0]->derive(var));
    auto *m = new function<mul>;
    m->childs[0] = std::move(ptr_type(new function<constant>(-1)));
    m->childs[1] = std::move(ptr_type(p));
    return ptr_type(m);
}

template <> inline expr::string_type function<struct cos>::to_string()
{ return "cos(" + n_ary::childs[0]->to_string() + ")"; }

template <>
inline expr::eval_type function<struct cos>::eval(
        const expr::valuation_type& val)
{ return std::cos(n_ary::childs[0]->eval(val)); }

/*******************************************************
 *****   function<tan> template specialisations    *****
 *******************************************************/

/*******************************************************
 *****   function<log> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<struct log>::derive(
        const expr::valuation_type::size_type& var) {
    auto *p = new function<struct div>;
    p->childs[0] = std::move(n_ary::childs[0]->derive(var));
    p->childs[1] = std::move(n_ary::childs[0]->clone());
    return ptr_type(p);
}

template <> inline expr::string_type function<struct log>::to_string()
{ return "log(" + n_ary::childs[0]->to_string() + ")"; };

template <>
inline expr::eval_type function<struct log>::eval(const expr::valuation_type& val)
{ return std::log(n_ary::childs[0]->eval(val)); }

/*******************************************************
 *****   function<add> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<add>::derive(
        const expr::valuation_type::size_type& var) {
	auto *p = new function<add>;
	p->childs[0] = std::move(n_ary::childs[0]->derive(var));
	p->childs[1] = std::move(n_ary::childs[1]->derive(var));
	return ptr_type(p);
}

template <> inline expr::string_type function<add>::to_string()
{ return n_ary::childs[0]->to_string() + "+" + n_ary::childs[1]->to_string(); }

template <>
inline expr::eval_type function<add>::eval(const expr::valuation_type& val)
{ return n_ary::childs[0]->eval(val) + n_ary::childs[1]->eval(val); }

/*******************************************************
 *****   function<sub> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<sub>::derive(
        const expr::valuation_type::size_type& var) {
    auto *p = new function<sub>;
    p->childs[0] = std::move(n_ary::childs[0]->derive(var));
    p->childs[1] = std::move(n_ary::childs[1]->derive(var));
    return ptr_type(p);
}

template <> inline expr::string_type function<sub>::to_string()
{ return n_ary::childs[0]->to_string() + "-" + n_ary::childs[1]->to_string(); }

template <>
inline expr::eval_type function<sub>::eval(const expr::valuation_type& val)
{ return n_ary::childs[0]->eval(val) - n_ary::childs[1]->eval(val); }

/*******************************************************
 *****   function<mul> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<mul>::derive(
        const expr::valuation_type::size_type& var) {
    auto *add_lhs = new function<mul>;
    add_lhs->childs[0] = std::move(n_ary::childs[0]->derive(var));
    add_lhs->childs[1] = std::move(n_ary::childs[1]->clone());
    auto *add_rhs = new function<mul>;
    add_rhs->childs[0] = std::move(n_ary::childs[0]->clone());
    add_rhs->childs[1] = std::move(n_ary::childs[1]->derive(var));
    auto *res = new function<add>;
    res->childs[0] = std::move(ptr_type(add_lhs));
    res->childs[1] = std::move(ptr_type(add_rhs));
    return ptr_type(res);
}

template <> inline expr::string_type function<mul>::to_string()
{ return n_ary::childs[0]->to_string() + "*" + n_ary::childs[1]->to_string(); }

template <>
inline expr::eval_type function<mul>::eval(const expr::valuation_type& val)
{ return n_ary::childs[0]->eval(val) * n_ary::childs[1]->eval(val); }

/*******************************************************
 *****   function<div> template specialisations    *****
 *******************************************************/

/*******************************************************
 *****   function<pow> template specialisations    *****
 *******************************************************/

#endif
<commit_msg>function<sin>::derive(...) repaired<commit_after>#ifndef EXPR_HPP
#define EXPR_HPP

#include <iostream>
#include <memory>
#include <string>
#include <array>
#include <vector>
#include <type_traits>
#include <cmath>

/**
 * Virtual super-class for expression tree
 *
 * All important types and functions for outside users are
 * defined here.
 */
class expr {
public:

	/* It might be beter to use policy class instead */
	using ptr_type = std::unique_ptr<expr>;
	using string_type = std::string;
	using eval_type = double;
	using valuation_type = std::vector<eval_type>;

	virtual ptr_type derive(const valuation_type::size_type& var) = 0;
	virtual ptr_type clone() = 0;
	virtual string_type to_string() = 0;
	virtual eval_type eval(const valuation_type& values) = 0;
};

/**
 * Type of expression tree.
 *
 * Tree is basically pointer. This helps to keep track of tree
 * ownership. When you have tree_type - you own pointer otherwise
 * when you have tree_type::element_type you do NOT own this tree.
 * So you shouldn't (musn't) explicitly delete it.
 *
 * The class satisfies the requirements of MoveConstructible and
 * MoveAssignable, but not the requirements of either
 * CopyConstructible or CopyAssignable.
 */
using tree_type = std::unique_ptr<expr>;

/**
 * Child (subtree) container.
 *
 * TODO : What is more appropriete polymorphic hierarchy?
 * +------+    +-------+    +----------+
 * | expr | <- | n_ary | <- | function |
 * +------+    +-------+    +----------+
 *
 *               OR
 *
 * +------+    +----------+
 * | expr | <- | function |
 * +------+    +----------+
 *              /
 * +-------+   /
 * | n_ary | <-
 * +-------+
 */
template <std::size_t Arity>
class n_ary : public expr {
protected:
	std::array<expr::ptr_type, Arity> childs;

    template <class T, class U> friend class function;
};

/**
 * Every function type must be derived from this class
 */
struct function_base { };

struct variable : public function_base {
	constexpr static std::size_t arity = 0;
    typedef expr::valuation_type::size_type value_type;
	value_type var_num;
};

struct constant : public function_base {
	constexpr static std::size_t arity = 0;
    typedef expr::eval_type value_type;
	value_type c;
};

struct sin : public function_base { constexpr static std::size_t arity = 1; };
struct cos : public function_base { constexpr static std::size_t arity = 1; };
struct tan : public function_base { constexpr static std::size_t arity = 1; };
struct log : public function_base { constexpr static std::size_t arity = 1; };

struct add : public function_base { constexpr static std::size_t arity = 2; };
struct sub : public function_base { constexpr static std::size_t arity = 2; };
struct mul : public function_base { constexpr static std::size_t arity = 2; };
struct div : public function_base { constexpr static std::size_t arity = 2; };
struct pow : public function_base { constexpr static std::size_t arity = 2; };

/**
 * Compile time type property deduction
 * Specialisation for specific templates should be sufficient but this is
 * more elegant and general
 */
template <typename T>
class has_value {
    typedef char yes[1];
    typedef char no[2];

    template <typename U>
    static yes& test(typename U::value_type*);
    template <typename U>
    static no& test(...);

public:
    enum { value = (sizeof(yes) == sizeof(test<T>(0))) };
};

/**
 * Function class with all functionality
 *
 * Template parameter must be derived from function_base class - this makes
 * more human-readable compiler errors when invalid template parameter is
 * supplied.
 *
 * TODO : Conditionally derive from n_ary only when T::arity != 0
 */
template <class T, class Enable = void>
class function;

template <class T>
class function<
    T,
    typename std::enable_if<
        std::is_base_of<
            function_base,
            T
        >::value
    >::type
>
  : public T, public n_ary<T::arity> {
public:
	/**
	 * Constructor for functions with internal value
	 * Defined only for functions with value_type type
	 *
	 * TODO : Is possible to simply pass more then one parameter
	 *        without additional encapsulation (pair, tuple, vector, ...)?
	 * TODO : define template <class T> function<T>::operator std::string();
	 */
	template <
            typename U = T,
            typename std::enable_if<
                    has_value<U>::value
                >::type ...
        >
	function(const typename U::value_type& value);

    function() {};
    explicit function(const function<T>&) { };

	virtual expr::ptr_type derive(const expr::valuation_type::size_type& var);

	virtual expr::ptr_type clone() {
		return expr::ptr_type(new function<T>(*this));
	};

	virtual expr::string_type to_string();
	virtual expr::eval_type eval(const expr::valuation_type& values);

};

template <
        class T,
        class = typename std::enable_if<
                std::is_base_of<
                        function_base,
                        T
                    >::value
            >::type
    >
expr::ptr_type construct(typename T::value_type v) {
	return expr::ptr_type(nullptr);
}

/**
 * Required prototypes
 */
//template <> template <>
//inline function<constant>::function(const constant::value_type& val);

//template <> template <>
//inline function<variable>::function(const variable::value_type& val);

/*******************************************************
 ***** function<variable> template specialisations *****
 *******************************************************/

template <> template <>
inline function<variable>::function(const variable::value_type& vnum)
{ variable::var_num = vnum; }

template <>
inline expr::ptr_type function<variable>::derive(
    const expr::valuation_type::size_type& n)
{ return ptr_type(new function<constant>(n == var_num ? 1 : 0)); }

template <> inline expr::string_type function<variable>::to_string()
{ return "x_" + std::to_string(variable::var_num); }

template <>
inline expr::eval_type function<variable>::eval(
    const expr::valuation_type& values)
{ return values[variable::var_num]; }

/*******************************************************
 ***** function<constant> template specialisations *****
 *******************************************************/

template <> template <>
inline function<constant>::function(const constant::value_type& val)
{ constant::c = val; }

template <>
inline expr::ptr_type function<constant>::derive(
    const expr::valuation_type::size_type&)
{ return ptr_type(new function<constant>(0)); }

template <> inline expr::string_type function<constant>::to_string()
{ return std::to_string(constant::c); }

template <>
inline expr::eval_type function<constant>::eval(const expr::valuation_type&)
{ return constant::c; }

/*******************************************************
 *****   function<sin> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<struct sin>::derive(
        const expr::valuation_type::size_type& var) {
    auto *p = new function<struct cos>;
    p->childs[0] = std::move(n_ary::childs[0]->clone());
    auto *m = new function<mul>;
    m->childs[0] = std::move(ptr_type(p));
    m->childs[1] = std::move(n_ary::childs[0]->derive(var));
    return ptr_type(m);
}

template <> inline expr::string_type function<struct sin>::to_string()
{ return "sin(" + n_ary::childs[0]->to_string() + ")"; }

template <>
inline expr::eval_type function<struct sin>::eval(
        const expr::valuation_type& val)
{ return std::sin(n_ary::childs[0]->eval(val)); }

/*******************************************************
 *****   function<cos> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<struct cos>::derive(
        const expr::valuation_type::size_type& var) {
    auto *s = new function<struct sin>;
    s->childs[0] = std::move(n_ary::childs[0]->clone());
    auto *p = new function<mul>;
    p->childs[0] = std::move(ptr_type(s));
    p->childs[1] = std::move(n_ary::childs[0]->derive(var));
    auto *m = new function<mul>;
    m->childs[0] = std::move(ptr_type(new function<constant>(-1)));
    m->childs[1] = std::move(ptr_type(p));
    return ptr_type(m);
}

template <> inline expr::string_type function<struct cos>::to_string()
{ return "cos(" + n_ary::childs[0]->to_string() + ")"; }

template <>
inline expr::eval_type function<struct cos>::eval(
        const expr::valuation_type& val)
{ return std::cos(n_ary::childs[0]->eval(val)); }

/*******************************************************
 *****   function<tan> template specialisations    *****
 *******************************************************/

/*******************************************************
 *****   function<log> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<struct log>::derive(
        const expr::valuation_type::size_type& var) {
    auto *p = new function<struct div>;
    p->childs[0] = std::move(n_ary::childs[0]->derive(var));
    p->childs[1] = std::move(n_ary::childs[0]->clone());
    return ptr_type(p);
}

template <> inline expr::string_type function<struct log>::to_string()
{ return "log(" + n_ary::childs[0]->to_string() + ")"; };

template <>
inline expr::eval_type function<struct log>::eval(const expr::valuation_type& val)
{ return std::log(n_ary::childs[0]->eval(val)); }

/*******************************************************
 *****   function<add> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<add>::derive(
        const expr::valuation_type::size_type& var) {
	auto *p = new function<add>;
	p->childs[0] = std::move(n_ary::childs[0]->derive(var));
	p->childs[1] = std::move(n_ary::childs[1]->derive(var));
	return ptr_type(p);
}

template <> inline expr::string_type function<add>::to_string()
{ return n_ary::childs[0]->to_string() + "+" + n_ary::childs[1]->to_string(); }

template <>
inline expr::eval_type function<add>::eval(const expr::valuation_type& val)
{ return n_ary::childs[0]->eval(val) + n_ary::childs[1]->eval(val); }

/*******************************************************
 *****   function<sub> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<sub>::derive(
        const expr::valuation_type::size_type& var) {
    auto *p = new function<sub>;
    p->childs[0] = std::move(n_ary::childs[0]->derive(var));
    p->childs[1] = std::move(n_ary::childs[1]->derive(var));
    return ptr_type(p);
}

template <> inline expr::string_type function<sub>::to_string()
{ return n_ary::childs[0]->to_string() + "-" + n_ary::childs[1]->to_string(); }

template <>
inline expr::eval_type function<sub>::eval(const expr::valuation_type& val)
{ return n_ary::childs[0]->eval(val) - n_ary::childs[1]->eval(val); }

/*******************************************************
 *****   function<mul> template specialisations    *****
 *******************************************************/

template <>
inline expr::ptr_type function<mul>::derive(
        const expr::valuation_type::size_type& var) {
    auto *add_lhs = new function<mul>;
    add_lhs->childs[0] = std::move(n_ary::childs[0]->derive(var));
    add_lhs->childs[1] = std::move(n_ary::childs[1]->clone());
    auto *add_rhs = new function<mul>;
    add_rhs->childs[0] = std::move(n_ary::childs[0]->clone());
    add_rhs->childs[1] = std::move(n_ary::childs[1]->derive(var));
    auto *res = new function<add>;
    res->childs[0] = std::move(ptr_type(add_lhs));
    res->childs[1] = std::move(ptr_type(add_rhs));
    return ptr_type(res);
}

template <> inline expr::string_type function<mul>::to_string()
{ return n_ary::childs[0]->to_string() + "*" + n_ary::childs[1]->to_string(); }

template <>
inline expr::eval_type function<mul>::eval(const expr::valuation_type& val)
{ return n_ary::childs[0]->eval(val) * n_ary::childs[1]->eval(val); }

/*******************************************************
 *****   function<div> template specialisations    *****
 *******************************************************/

/*******************************************************
 *****   function<pow> template specialisations    *****
 *******************************************************/

#endif
<|endoftext|>