<commit_before>/****************************************************************************
 *
 * Copyright (c) 2015 Mark Charlebois. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file vdev_posix.cpp
 *
 * POSIX-like API for virtual character device
 */

#include <px4_log.h>
#include <px4_posix.h>
#include <px4_time.h>
#include "device.h"
#include "vfile.h"

#include <hrt_work.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

using namespace device;

pthread_mutex_t filemutex = PTHREAD_MUTEX_INITIALIZER;

extern "C" {

#define PX4_MAX_FD 200
	static device::file_t *filemap[PX4_MAX_FD] = {};

	int px4_errno;

	inline bool valid_fd(int fd)
	{
		pthread_mutex_lock(&filemutex);
		bool ret = (fd < PX4_MAX_FD && fd >= 0 && filemap[fd] != NULL);
		pthread_mutex_unlock(&filemutex);
		return ret;
	}

	inline VDev *get_vdev(int fd)
	{
		pthread_mutex_lock(&filemutex);
		bool valid = (fd < PX4_MAX_FD && fd >= 0 && filemap[fd] != NULL);
		VDev *dev;

		if (valid) {
			dev = (VDev *)(filemap[fd]->vdev);

		} else {
			dev = nullptr;
		}

		pthread_mutex_unlock(&filemutex);
		return dev;
	}

	int px4_open(const char *path, int flags, ...)
	{
		PX4_DEBUG("px4_open");
		VDev *dev = VDev::getDev(path);
		int ret = 0;
		int i;
		mode_t mode;

		if (!dev && (flags & (PX4_F_WRONLY | PX4_F_CREAT)) != 0 &&
		    strncmp(path, "/obj/", 5) != 0 &&
		    strncmp(path, "/dev/", 5) != 0) {
			va_list p;
			va_start(p, flags);
			mode = va_arg(p, int);
			va_end(p);

			// Create the file
			PX4_DEBUG("Creating virtual file %s", path);
			dev = VFile::createFile(path, mode);
		}

		if (dev) {

			pthread_mutex_lock(&filemutex);

			for (i = 0; i < PX4_MAX_FD; ++i) {
				if (filemap[i] == 0) {
					filemap[i] = new device::file_t(flags, dev, i);
					break;
				}
			}

			pthread_mutex_unlock(&filemutex);

			if (i < PX4_MAX_FD) {
				ret = dev->open(filemap[i]);

			} else {
				PX4_WARN("exceeded maximum number of file descriptors!");
				ret = -ENOENT;
			}

		} else {
			ret = -EINVAL;
		}

		if (ret < 0) {
			px4_errno = -ret;
			return -1;
		}

		PX4_DEBUG("px4_open fd = %d", filemap[i]->fd);
		return filemap[i]->fd;
	}

	int px4_close(int fd)
	{
		int ret;

		VDev *dev = get_vdev(fd);

		if (dev) {
			pthread_mutex_lock(&filemutex);
			ret = dev->close(filemap[fd]);
			filemap[fd] = nullptr;
			pthread_mutex_unlock(&filemutex);
			PX4_DEBUG("px4_close fd = %d", fd);

		} else {
			ret = -EINVAL;
		}

		if (ret < 0) {
			px4_errno = -ret;
			ret = PX4_ERROR;
		}

		return ret;
	}

	ssize_t px4_read(int fd, void *buffer, size_t buflen)
	{
		int ret;

		VDev *dev = get_vdev(fd);

		if (dev) {
			PX4_DEBUG("px4_read fd = %d", fd);
			ret = dev->read(filemap[fd], (char *)buffer, buflen);

		} else {
			ret = -EINVAL;
		}

		if (ret < 0) {
			px4_errno = -ret;
			ret = PX4_ERROR;
		}

		return ret;
	}

	ssize_t px4_write(int fd, const void *buffer, size_t buflen)
	{
		int ret;

		VDev *dev = get_vdev(fd);

		if (dev) {
			PX4_DEBUG("px4_write fd = %d", fd);
			ret = dev->write(filemap[fd], (const char *)buffer, buflen);

		} else {
			ret = -EINVAL;
		}

		if (ret < 0) {
			px4_errno = -ret;
			ret = PX4_ERROR;
		}

		return ret;
	}

	int px4_ioctl(int fd, int cmd, unsigned long arg)
	{
		PX4_DEBUG("px4_ioctl fd = %d", fd);
		int ret = 0;

		VDev *dev = get_vdev(fd);

		if (dev) {
			ret = dev->ioctl(filemap[fd], cmd, arg);

		} else {
			ret = -EINVAL;
		}

		if (ret < 0) {
			px4_errno = -ret;
		}

		return ret;
	}

	int px4_poll(px4_pollfd_struct_t *fds, nfds_t nfds, int timeout)
	{
		if (nfds == 0) {
			PX4_WARN("px4_poll with no fds");
			return -1;
		}

		px4_sem_t sem;
		int count = 0;
		int ret = -1;
		unsigned int i;

		const unsigned NAMELEN = 32;
		char thread_name[NAMELEN] = {};

#ifndef __PX4_QURT
		int nret = pthread_getname_np(pthread_self(), thread_name, NAMELEN);

		if (nret || thread_name[0] == 0) {
			PX4_WARN("failed getting thread name");
		}

#endif

		PX4_DEBUG("Called px4_poll timeout = %d", timeout);
		px4_sem_init(&sem, 0, 0);

		// Go through all fds and check them for a pollable state
		bool fd_pollable = false;

		for (i = 0; i < nfds; ++i) {
			fds[i].sem     = &sem;
			fds[i].revents = 0;
			fds[i].priv    = NULL;

			VDev *dev = get_vdev(fds[i].fd);

			// If fd is valid
			if (dev) {
				PX4_DEBUG("%s: px4_poll: VDev->poll(setup) %d", thread_name, fds[i].fd);
				ret = dev->poll(filemap[fds[i].fd], &fds[i], true);

				if (ret < 0) {
					PX4_WARN("%s: px4_poll() error: %s",
						 thread_name, strerror(errno));
					break;
				}

				if (ret >= 0) {
					fd_pollable = true;
				}
			}
		}

		// If any FD can be polled, lock the semaphore and
		// check for new data
		if (fd_pollable) {
			if (timeout > 0) {

				// Get the current time
				struct timespec ts;
				px4_clock_gettime(CLOCK_REALTIME, &ts);

				// Calculate an absolute time in the future
				const unsigned billion = (1000 * 1000 * 1000);
				unsigned tdiff = timeout;
				uint64_t nsecs = ts.tv_nsec + (tdiff * 1000 * 1000);
				ts.tv_sec += nsecs / billion;
				nsecs -= (nsecs / billion) * billion;
				ts.tv_nsec = nsecs;

				// Execute a blocking wait for that time in the future
				errno = 0;
				ret = px4_sem_timedwait(&sem, &ts);
#ifndef __PX4_DARWIN
				ret = errno;
#endif

				// Ensure ret is negative on failure
				if (ret > 0) {
					ret = -ret;
				}

				if (ret && ret != -ETIMEDOUT) {
					PX4_WARN("%s: px4_poll() sem error", thread_name);
				}

			} else if (timeout < 0) {
				px4_sem_wait(&sem);
			}

			// We have waited now (or not, depending on timeout),
			// go through all fds and count how many have data
			for (i = 0; i < nfds; ++i) {

				VDev *dev = get_vdev(fds[i].fd);

				// If fd is valid
				if (dev) {
					PX4_DEBUG("%s: px4_poll: VDev->poll(teardown) %d", thread_name, fds[i].fd);
					ret = dev->poll(filemap[fds[i].fd], &fds[i], false);

					if (ret < 0) {
						PX4_WARN("%s: px4_poll() 2nd poll fail", thread_name);
						break;
					}

					if (fds[i].revents) {
						count += 1;
					}
				}
			}
		}

		px4_sem_destroy(&sem);

		// Return the positive count if present,
		// return the negative error number if failed
		return (count) ? count : ret;
	}

	int px4_fsync(int fd)
	{
		return 0;
	}

	int px4_access(const char *pathname, int mode)
	{
		if (mode != F_OK) {
			errno = EINVAL;
			return -1;
		}

		VDev *dev = VDev::getDev(pathname);
		return (dev != nullptr) ? 0 : -1;
	}

	void px4_show_devices()
	{
		VDev::showDevices();
	}

	void px4_show_topics()
	{
		VDev::showTopics();
	}

	void px4_show_files()
	{
		VDev::showFiles();
	}

	const char *px4_get_device_names(unsigned int *handle)
	{
		return VDev::devList(handle);
	}

	const char *px4_get_topic_names(unsigned int *handle)
	{
		return VDev::topicList(handle);
	}

}

<commit_msg>POSIX: Warn about file descriptor exceed with associated thread name<commit_after>/****************************************************************************
 *
 * Copyright (c) 2015 Mark Charlebois. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file vdev_posix.cpp
 *
 * POSIX-like API for virtual character device
 */

#include <px4_log.h>
#include <px4_posix.h>
#include <px4_time.h>
#include "device.h"
#include "vfile.h"

#include <hrt_work.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

using namespace device;

pthread_mutex_t filemutex = PTHREAD_MUTEX_INITIALIZER;

extern "C" {

#define PX4_MAX_FD 200
	static device::file_t *filemap[PX4_MAX_FD] = {};

	int px4_errno;

	inline bool valid_fd(int fd)
	{
		pthread_mutex_lock(&filemutex);
		bool ret = (fd < PX4_MAX_FD && fd >= 0 && filemap[fd] != NULL);
		pthread_mutex_unlock(&filemutex);
		return ret;
	}

	inline VDev *get_vdev(int fd)
	{
		pthread_mutex_lock(&filemutex);
		bool valid = (fd < PX4_MAX_FD && fd >= 0 && filemap[fd] != NULL);
		VDev *dev;

		if (valid) {
			dev = (VDev *)(filemap[fd]->vdev);

		} else {
			dev = nullptr;
		}

		pthread_mutex_unlock(&filemutex);
		return dev;
	}

	int px4_open(const char *path, int flags, ...)
	{
		PX4_DEBUG("px4_open");
		VDev *dev = VDev::getDev(path);
		int ret = 0;
		int i;
		mode_t mode;

		if (!dev && (flags & (PX4_F_WRONLY | PX4_F_CREAT)) != 0 &&
		    strncmp(path, "/obj/", 5) != 0 &&
		    strncmp(path, "/dev/", 5) != 0) {
			va_list p;
			va_start(p, flags);
			mode = va_arg(p, int);
			va_end(p);

			// Create the file
			PX4_DEBUG("Creating virtual file %s", path);
			dev = VFile::createFile(path, mode);
		}

		if (dev) {

			pthread_mutex_lock(&filemutex);

			for (i = 0; i < PX4_MAX_FD; ++i) {
				if (filemap[i] == 0) {
					filemap[i] = new device::file_t(flags, dev, i);
					break;
				}
			}

			pthread_mutex_unlock(&filemutex);

			if (i < PX4_MAX_FD) {
				ret = dev->open(filemap[i]);

			} else {

				const unsigned NAMELEN = 32;
				char thread_name[NAMELEN] = {};

#ifndef __PX4_QURT
				int nret = pthread_getname_np(pthread_self(), thread_name, NAMELEN);

				if (nret || thread_name[0] == 0) {
					PX4_WARN("failed getting thread name");
				}

#endif

				PX4_WARN("%s: exceeded maximum number of file descriptors!", thread_name);
				ret = -ENOENT;
			}

		} else {
			ret = -EINVAL;
		}

		if (ret < 0) {
			px4_errno = -ret;
			return -1;
		}

		PX4_DEBUG("px4_open fd = %d", filemap[i]->fd);
		return filemap[i]->fd;
	}

	int px4_close(int fd)
	{
		int ret;

		VDev *dev = get_vdev(fd);

		if (dev) {
			pthread_mutex_lock(&filemutex);
			ret = dev->close(filemap[fd]);
			filemap[fd] = nullptr;
			pthread_mutex_unlock(&filemutex);
			PX4_DEBUG("px4_close fd = %d", fd);

		} else {
			ret = -EINVAL;
		}

		if (ret < 0) {
			px4_errno = -ret;
			ret = PX4_ERROR;
		}

		return ret;
	}

	ssize_t px4_read(int fd, void *buffer, size_t buflen)
	{
		int ret;

		VDev *dev = get_vdev(fd);

		if (dev) {
			PX4_DEBUG("px4_read fd = %d", fd);
			ret = dev->read(filemap[fd], (char *)buffer, buflen);

		} else {
			ret = -EINVAL;
		}

		if (ret < 0) {
			px4_errno = -ret;
			ret = PX4_ERROR;
		}

		return ret;
	}

	ssize_t px4_write(int fd, const void *buffer, size_t buflen)
	{
		int ret;

		VDev *dev = get_vdev(fd);

		if (dev) {
			PX4_DEBUG("px4_write fd = %d", fd);
			ret = dev->write(filemap[fd], (const char *)buffer, buflen);

		} else {
			ret = -EINVAL;
		}

		if (ret < 0) {
			px4_errno = -ret;
			ret = PX4_ERROR;
		}

		return ret;
	}

	int px4_ioctl(int fd, int cmd, unsigned long arg)
	{
		PX4_DEBUG("px4_ioctl fd = %d", fd);
		int ret = 0;

		VDev *dev = get_vdev(fd);

		if (dev) {
			ret = dev->ioctl(filemap[fd], cmd, arg);

		} else {
			ret = -EINVAL;
		}

		if (ret < 0) {
			px4_errno = -ret;
		}

		return ret;
	}

	int px4_poll(px4_pollfd_struct_t *fds, nfds_t nfds, int timeout)
	{
		if (nfds == 0) {
			PX4_WARN("px4_poll with no fds");
			return -1;
		}

		px4_sem_t sem;
		int count = 0;
		int ret = -1;
		unsigned int i;

		const unsigned NAMELEN = 32;
		char thread_name[NAMELEN] = {};

#ifndef __PX4_QURT
		int nret = pthread_getname_np(pthread_self(), thread_name, NAMELEN);

		if (nret || thread_name[0] == 0) {
			PX4_WARN("failed getting thread name");
		}

#endif

		PX4_DEBUG("Called px4_poll timeout = %d", timeout);
		px4_sem_init(&sem, 0, 0);

		// Go through all fds and check them for a pollable state
		bool fd_pollable = false;

		for (i = 0; i < nfds; ++i) {
			fds[i].sem     = &sem;
			fds[i].revents = 0;
			fds[i].priv    = NULL;

			VDev *dev = get_vdev(fds[i].fd);

			// If fd is valid
			if (dev) {
				PX4_DEBUG("%s: px4_poll: VDev->poll(setup) %d", thread_name, fds[i].fd);
				ret = dev->poll(filemap[fds[i].fd], &fds[i], true);

				if (ret < 0) {
					PX4_WARN("%s: px4_poll() error: %s",
						 thread_name, strerror(errno));
					break;
				}

				if (ret >= 0) {
					fd_pollable = true;
				}
			}
		}

		// If any FD can be polled, lock the semaphore and
		// check for new data
		if (fd_pollable) {
			if (timeout > 0) {

				// Get the current time
				struct timespec ts;
				px4_clock_gettime(CLOCK_REALTIME, &ts);

				// Calculate an absolute time in the future
				const unsigned billion = (1000 * 1000 * 1000);
				unsigned tdiff = timeout;
				uint64_t nsecs = ts.tv_nsec + (tdiff * 1000 * 1000);
				ts.tv_sec += nsecs / billion;
				nsecs -= (nsecs / billion) * billion;
				ts.tv_nsec = nsecs;

				// Execute a blocking wait for that time in the future
				errno = 0;
				ret = px4_sem_timedwait(&sem, &ts);
#ifndef __PX4_DARWIN
				ret = errno;
#endif

				// Ensure ret is negative on failure
				if (ret > 0) {
					ret = -ret;
				}

				if (ret && ret != -ETIMEDOUT) {
					PX4_WARN("%s: px4_poll() sem error", thread_name);
				}

			} else if (timeout < 0) {
				px4_sem_wait(&sem);
			}

			// We have waited now (or not, depending on timeout),
			// go through all fds and count how many have data
			for (i = 0; i < nfds; ++i) {

				VDev *dev = get_vdev(fds[i].fd);

				// If fd is valid
				if (dev) {
					PX4_DEBUG("%s: px4_poll: VDev->poll(teardown) %d", thread_name, fds[i].fd);
					ret = dev->poll(filemap[fds[i].fd], &fds[i], false);

					if (ret < 0) {
						PX4_WARN("%s: px4_poll() 2nd poll fail", thread_name);
						break;
					}

					if (fds[i].revents) {
						count += 1;
					}
				}
			}
		}

		px4_sem_destroy(&sem);

		// Return the positive count if present,
		// return the negative error number if failed
		return (count) ? count : ret;
	}

	int px4_fsync(int fd)
	{
		return 0;
	}

	int px4_access(const char *pathname, int mode)
	{
		if (mode != F_OK) {
			errno = EINVAL;
			return -1;
		}

		VDev *dev = VDev::getDev(pathname);
		return (dev != nullptr) ? 0 : -1;
	}

	void px4_show_devices()
	{
		VDev::showDevices();
	}

	void px4_show_topics()
	{
		VDev::showTopics();
	}

	void px4_show_files()
	{
		VDev::showFiles();
	}

	const char *px4_get_device_names(unsigned int *handle)
	{
		return VDev::devList(handle);
	}

	const char *px4_get_topic_names(unsigned int *handle)
	{
		return VDev::topicList(handle);
	}

}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: b1drange.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: thb $ $Date: 2004-02-16 17:03:07 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _BGFX_RANGE_B1DRANGE_HXX
#define _BGFX_RANGE_B1DRANGE_HXX

#ifndef _BGFX_RANGE_BASICRANGE_HXX
#include <basegfx/range/basicrange.hxx>
#endif

namespace basegfx
{
    class B1DRange
    {
        ::basegfx::BasicRange< double, DoubleTraits >   maRange;

    public:
        B1DRange()
        {
        }

        explicit B1DRange(double fStartValue)
        :   maRange(fStartValue)
        {
        }

        B1DRange(double fStartValue1, double fStartValue2)
        :   maRange(fStartValue1)
        {
            expand(fStartValue2);
        }

        B1DRange(const B1DRange& rRange)
        :   maRange(rRange.maRange)
        {
        }

        bool isEmpty() const
        {
            return maRange.isEmpty();
        }

        void reset()
        {
            maRange.reset();
        }

        bool operator==( const B1DRange& rRange ) const
        {
            return (maRange == rRange.maRange);
        }

        bool operator!=( const B1DRange& rRange ) const
        {
            return (maRange != rRange.maRange);
        }

        void operator=(const B1DRange& rRange)
        {
            maRange = rRange.maRange;
        }

        double getMinimum() const
        {
            return maRange.getMinimum();
        }

        double getMaximum() const
        {
            return maRange.getMaximum();
        }

        double getRange() const
        {
            return maRange.getRange();
        }

        double getCenter() const
        {
            return maRange.getCenter();
        }

        bool isInside(double fValue) const
        {
            return maRange.isInside(fValue);
        }

        bool isInside(const B1DRange& rRange) const
        {
            return maRange.isInside(rRange.maRange);
        }

        bool overlaps(const B1DRange& rRange) const
        {
            return maRange.overlaps(rRange.maRange);
        }

        void expand(double fValue)
        {
            maRange.expand(fValue);
        }

        void expand(const B1DRange& rRange)
        {
            maRange.expand(rRange.maRange);
        }

        void grow(double fValue)
        {
            maRange.grow(fValue);
        }
    };
} // end of namespace basegfx

#endif /* _BGFX_RANGE_B1DRANGE_HXX */
<commit_msg>INTEGRATION: CWS presentationengine01 (1.9.2); FILE MERGED 2004/11/20 00:00:35 thb 1.9.2.3: #110496# After-merge cleanups, finished BxD<->BxI conversions for range and tuples 2004/11/17 20:20:08 thb 1.9.2.2: #110496# Unified integer constructors/fround converters 2004/09/23 20:19:05 thb 1.9.2.1: #110496# Added intersect method to all range types<commit_after>/*************************************************************************
 *
 *  $RCSfile: b1drange.hxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 18:34:00 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _BGFX_RANGE_B1DRANGE_HXX
#define _BGFX_RANGE_B1DRANGE_HXX

#ifndef _BGFX_RANGE_BASICRANGE_HXX
#include <basegfx/range/basicrange.hxx>
#endif

namespace basegfx
{
    class B1IRange;

    class B1DRange
    {
        ::basegfx::BasicRange< double, DoubleTraits >   maRange;

    public:
        B1DRange()
        {
        }

        explicit B1DRange(double fStartValue)
        :   maRange(fStartValue)
        {
        }

        B1DRange(double fStartValue1, double fStartValue2)
        :   maRange(fStartValue1)
        {
            expand(fStartValue2);
        }

        B1DRange(const B1DRange& rRange)
        :   maRange(rRange.maRange)
        {
        }

        explicit B1DRange( const B1IRange& rRange );

        bool isEmpty() const
        {
            return maRange.isEmpty();
        }

        void reset()
        {
            maRange.reset();
        }

        bool operator==( const B1DRange& rRange ) const
        {
            return (maRange == rRange.maRange);
        }

        bool operator!=( const B1DRange& rRange ) const
        {
            return (maRange != rRange.maRange);
        }

        void operator=(const B1DRange& rRange)
        {
            maRange = rRange.maRange;
        }

        double getMinimum() const
        {
            return maRange.getMinimum();
        }

        double getMaximum() const
        {
            return maRange.getMaximum();
        }

        double getRange() const
        {
            return maRange.getRange();
        }

        double getCenter() const
        {
            return maRange.getCenter();
        }

        bool isInside(double fValue) const
        {
            return maRange.isInside(fValue);
        }

        bool isInside(const B1DRange& rRange) const
        {
            return maRange.isInside(rRange.maRange);
        }

        bool overlaps(const B1DRange& rRange) const
        {
            return maRange.overlaps(rRange.maRange);
        }

        void expand(double fValue)
        {
            maRange.expand(fValue);
        }

        void expand(const B1DRange& rRange)
        {
            maRange.expand(rRange.maRange);
        }

        void intersect(const B1DRange& rRange)
        {
            maRange.intersect(rRange.maRange);
        }

        void grow(double fValue)
        {
            maRange.grow(fValue);
        }
    };

    /** Round double to nearest integer for 1D range

        @return the nearest integer for this range
    */
    B1IRange fround(const B1DRange& rRange);
} // end of namespace basegfx

#endif /* _BGFX_RANGE_B1DRANGE_HXX */
<|endoftext|>


<commit_before>// Copyright Daniel Wallin & Arvid Norberg 2009. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/python.hpp>
#include <libtorrent/create_torrent.hpp>
#include <libtorrent/file_storage.hpp>
#include "libtorrent/intrusive_ptr_base.hpp"

using namespace boost::python;
using namespace libtorrent;

namespace
{
    void set_hash(create_torrent& c, int p, char const* hash)
    {
        c.set_hash(p, sha1_hash(hash));
    }

    void call_python_object(boost::python::object const& obj, int i)
    {
       obj(i);
    }

    void set_piece_hashes_callback(create_torrent& c, std::string const& p
        , boost::python::object cb)
    {
        set_piece_hashes(c, p, boost::bind(call_python_object, cb, _1));
    }
}

void bind_create_torrent()
{
    void (file_storage::*add_file0)(file_entry const&) = &file_storage::add_file;
    void (file_storage::*add_file1)(std::string const&, size_type, int, std::time_t, std::string const&) = &file_storage::add_file;
#if TORRENT_USE_WSTRING
    void (file_storage::*add_file2)(std::wstring const&, size_type, int, std::time_t, std::string const&) = &file_storage::add_file;
#endif

    void (file_storage::*set_name0)(std::string const&) = &file_storage::set_name;
#if TORRENT_USE_WSTRING
    void (file_storage::*set_name1)(std::wstring const&) = &file_storage::set_name;
#endif

    void (*set_piece_hashes0)(create_torrent&, std::string const&) = &set_piece_hashes;
    void (*add_files0)(file_storage&, std::string const&) = add_files;

    class_<file_storage>("file_storage")
        .def("is_valid", &file_storage::is_valid)
        .def("add_file", add_file0)
        .def("add_file", add_file1, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
#if TORRENT_USE_WSTRING
        .def("add_file", add_file2, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
#endif
        .def("num_files", &file_storage::num_files)
        .def("at", &file_storage::at, return_internal_reference<>())
        .def("total_size", &file_storage::total_size)
        .def("set_num_pieces", &file_storage::set_num_pieces)
        .def("num_pieces", &file_storage::num_pieces)
        .def("set_piece_length", &file_storage::set_piece_length)
        .def("piece_length", &file_storage::piece_length)
        .def("piece_size", &file_storage::piece_size)
        .def("set_name", set_name0)
#if TORRENT_USE_WSTRING
        .def("set_name", set_name1)
#endif
        .def("name", &file_storage::name, return_internal_reference<>())
        ;

    class_<create_torrent>("create_torrent", no_init)
        .def(init<file_storage&>())
        .def(init<file_storage&, int>())

        .def("generate", &create_torrent::generate)

        .def("files", &create_torrent::files, return_internal_reference<>())
        .def("set_comment", &create_torrent::set_comment)
        .def("set_creator", &create_torrent::set_creator)
        .def("set_hash", &set_hash)
        .def("add_url_seed", &create_torrent::add_url_seed)
        .def("add_node", &create_torrent::add_node)
        .def("add_tracker", &create_torrent::add_tracker)
        .def("set_priv", &create_torrent::set_priv)
        .def("num_pieces", &create_torrent::num_pieces)
        .def("piece_length", &create_torrent::piece_length)
        .def("piece_size", &create_torrent::piece_size)
        .def("priv", &create_torrent::priv)
        ;

    def("add_files", add_files0);
    def("set_piece_hashes", set_piece_hashes0);
    def("set_piece_hashes", set_piece_hashes_callback);

}
<commit_msg>fixed python binding build<commit_after>// Copyright Daniel Wallin & Arvid Norberg 2009. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/python.hpp>
#include <libtorrent/create_torrent.hpp>
#include <libtorrent/file_storage.hpp>
#include "libtorrent/intrusive_ptr_base.hpp"

using namespace boost::python;
using namespace libtorrent;

namespace
{
    void set_hash(create_torrent& c, int p, char const* hash)
    {
        c.set_hash(p, sha1_hash(hash));
    }

    void call_python_object(boost::python::object const& obj, int i)
    {
       obj(i);
    }

    void set_piece_hashes_callback(create_torrent& c, std::string const& p
        , boost::python::object cb)
    {
        set_piece_hashes(c, p, boost::bind(call_python_object, cb, _1));
    }
}

void bind_create_torrent()
{
    void (file_storage::*add_file0)(file_entry const&) = &file_storage::add_file;
    void (file_storage::*add_file1)(std::string const&, size_type, int, std::time_t, std::string const&) = &file_storage::add_file;
#if TORRENT_USE_WSTRING
    void (file_storage::*add_file2)(std::wstring const&, size_type, int, std::time_t, std::string const&) = &file_storage::add_file;
#endif

    void (file_storage::*set_name0)(std::string const&) = &file_storage::set_name;
#if TORRENT_USE_WSTRING
    void (file_storage::*set_name1)(std::wstring const&) = &file_storage::set_name;
#endif

    void (*set_piece_hashes0)(create_torrent&, std::string const&) = &set_piece_hashes;
    void (*add_files0)(file_storage&, std::string const&, boost::uint32_t) = add_files;

    class_<file_storage>("file_storage")
        .def("is_valid", &file_storage::is_valid)
        .def("add_file", add_file0)
        .def("add_file", add_file1, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
#if TORRENT_USE_WSTRING
        .def("add_file", add_file2, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
#endif
        .def("num_files", &file_storage::num_files)
        .def("at", &file_storage::at, return_internal_reference<>())
        .def("total_size", &file_storage::total_size)
        .def("set_num_pieces", &file_storage::set_num_pieces)
        .def("num_pieces", &file_storage::num_pieces)
        .def("set_piece_length", &file_storage::set_piece_length)
        .def("piece_length", &file_storage::piece_length)
        .def("piece_size", &file_storage::piece_size)
        .def("set_name", set_name0)
#if TORRENT_USE_WSTRING
        .def("set_name", set_name1)
#endif
        .def("name", &file_storage::name, return_internal_reference<>())
        ;

    class_<create_torrent>("create_torrent", no_init)
        .def(init<file_storage&>())
        .def(init<file_storage&, int>())

        .def("generate", &create_torrent::generate)

        .def("files", &create_torrent::files, return_internal_reference<>())
        .def("set_comment", &create_torrent::set_comment)
        .def("set_creator", &create_torrent::set_creator)
        .def("set_hash", &set_hash)
        .def("add_url_seed", &create_torrent::add_url_seed)
        .def("add_node", &create_torrent::add_node)
        .def("add_tracker", &create_torrent::add_tracker)
        .def("set_priv", &create_torrent::set_priv)
        .def("num_pieces", &create_torrent::num_pieces)
        .def("piece_length", &create_torrent::piece_length)
        .def("piece_size", &create_torrent::piece_size)
        .def("priv", &create_torrent::priv)
        ;

    def("add_files", add_files0);
    def("set_piece_hashes", set_piece_hashes0);
    def("set_piece_hashes", set_piece_hashes_callback);

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010, Directed Edge, Inc. | Licensed under the MPL and LGPL
 */

#include "QActiveResource.h"
#include <QXmlStreamReader>
#include <QStringList>
#include <QDateTime>
#include <QDebug>
#include <curl/curl.h>

using namespace QActiveResource;

static const QString QActiveResourceClassKey = "QActiveResource Class";

static size_t writer(void *ptr, size_t size, size_t nmemb, void *stream)
{
    reinterpret_cast<QByteArray *>(stream)->append(QByteArray((const char *)(ptr), size * nmemb));
    return size * nmemb;
}

namespace HTTP
{
    QByteArray get(const QUrl &url, bool followRedirects = false)
    {
        QByteArray data;
        CURL *curl = curl_easy_init();

        static const int maxRetry = 1;
        int retry = 0;

        if(curl)
        {
            do
            {
                curl_easy_setopt(curl, CURLOPT_URL, url.toEncoded().data());
                curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
                curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &data);
                curl_easy_setopt(curl, CURLOPT_TIMEOUT, 25);
                curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);

                if(followRedirects)
                {
                    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
                    curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1);
                    curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 2);
                }
            }
            while(curl_easy_perform(curl) != 0 && ++retry <= maxRetry);
            curl_easy_cleanup(curl);
        }

        return data;
    }
}

static QVariant::Type lookupType(const QString &name)
{
    static QHash<QString, QVariant::Type> types;

    if(types.isEmpty())
    {
        types["integer"] = QVariant::Int;
        types["decimal"] = QVariant::Double;
        types["datetime"] = QVariant::DateTime;
        types["boolean"] = QVariant::Bool;
    }

    return types.contains(name) ? types[name] : QVariant::String;
}

static void assign(Record *record, QString name, const QVariant &value)
{
    (*record)[name.replace('-', '_')] = value;
}

static QDateTime toDateTime(const QString &s)
{
    QDateTime time = QDateTime::fromString(s.left(s.length() - 6), Qt::ISODate);

    time.setTimeSpec(Qt::UTC);

    int zoneHours = s.mid(s.length() - 6, 3).toInt();
    int zoneMinutes = s.right(2).toInt();

    return time.addSecs(-1 * (60 * zoneHours + zoneMinutes) * 60);
}

static QString toClassName(QString name)
{
    if(name.isEmpty())
    {
        return name;
    }

    name[0] = name[0].toUpper();

    QRegExp re("-([a-z])");

    while(name.indexOf(re) >= 0)
    {
        name.replace(re.cap(0), re.cap(1).toUpper());
    }

    return name;
}

static QVariant extractFromRecord(const QVariant &record)
{
    QVariantHash hash = record.toHash();
    QStringList keys = hash.keys();
    keys.removeOne(QActiveResourceClassKey);
    return hash[keys.front()];
}

static bool hasNext(const QXmlStreamReader &xml)
{
    return (xml.tokenType() == QXmlStreamReader::StartElement ||
            (xml.tokenType() == QXmlStreamReader::Characters && xml.isWhitespace()));
}

static QVariant reader(QXmlStreamReader &xml, bool advance, bool isHash)
{
    Record record;
    QString elementName;

    while(!xml.atEnd())
    {
        if(advance)
        {
            xml.readNext();
        }
        if(xml.tokenType() == QXmlStreamReader::StartElement)
        {
            if(elementName.isNull())
            {
                elementName = xml.name().toString();
            }

            QString type = xml.attributes().value("type").toString();

            if(type == "array")
            {
                QString name = xml.name().toString();
                QVariantList array;

                while(xml.readNext() && hasNext(xml))
                {
                    if(!xml.isWhitespace())
                    {
                        array.append(reader(xml, false, false));
                    }
                }

                assign(&record, name, array);
            }
            else if(xml.attributes().value("nil") == "true")
            {
                assign(&record, xml.name().toString(), QVariant());
            }
            else if((advance && xml.name() != elementName) || isHash)
            {
                QString name = xml.name().toString();

                while(xml.readNext() && xml.isWhitespace()) {}

                if(xml.tokenType() == QXmlStreamReader::StartElement)
                {
                    Record sub;
                    sub.setClassName(toClassName(name));

                    while(hasNext(xml))
                    {
                        if(!xml.isWhitespace())
                        {
                            QString subName = xml.name().toString();
                            assign(&sub, subName, extractFromRecord(reader(xml, false, true)));
                        }
                        xml.readNext();
                    }

                    assign(&record, name, sub);
                }
                else
                {
                    QVariant value;
                    QString text = xml.text().toString();

                    switch(lookupType(type))
                    {
                    case QVariant::Int:
                        value = text.toInt();
                        break;
                    case QVariant::Double:
                        value = text.toDouble();
                        break;
                    case QVariant::DateTime:
                        value = toDateTime(text);
                        break;
                    case QVariant::Bool:
                        value = bool(text == "true");
                        break;
                    default:
                        value = text.isEmpty() ? QVariant() : text;
                    }

                    assign(&record, name, value);
                }
            }
        }
        if(xml.tokenType() == QXmlStreamReader::EndElement &&
           !elementName.isNull() && elementName == xml.name())
        {
            record.setClassName(toClassName(elementName));
            return record;
        }

        advance = true;
    }

    return QVariant();
}

static RecordList fetch(QUrl url, bool followRedirects = false)
{
    if(!url.path().endsWith(".xml"))
    {
        url.setPath(url.path() + ".xml");
    }

    QByteArray data = HTTP::get(url, followRedirects);

    QXmlStreamReader xml(data);

    QVariant value = reader(xml, true, false);
    RecordList records;

    if(value.type() == QVariant::List)
    {
        foreach(QVariant v, value.toList())
        {
            records.append(v.toHash());
        }
    }
    else if(value.type() == QVariant::Hash && value.toHash().size() == 2)
    {
        foreach(QVariant v, extractFromRecord(value).toList())
        {
            records.append(v.toHash());
        }
    }
    else if(value.isValid())
    {
        records.append(value.toHash());
    }

    return records;
}

/*
 * Record
 */

Record::Record(const QVariantHash &hash) :
    d(new Data)
{
    d->hash = hash;
    d->className = d->hash.take(QActiveResourceClassKey).toString();
}

Record::Record(const QVariant &v) :
    d(new Data)
{
    d->hash = v.toHash();
    d->className = d->hash.take(QActiveResourceClassKey).toString();
}

QVariant &Record::operator[](const QString &key)
{
    return d->hash[key];
}

QVariant Record::operator[](const QString &key) const
{
    return d->hash[key];
}

bool Record::isEmpty() const
{
    return d->hash.isEmpty();
}

QString Record::className() const
{
    return d->className;
}

void Record::setClassName(const QString &name)
{
    d->className = name;
}

Record::operator QVariant() const
{
    QVariantHash hash = d->hash;
    hash[QActiveResourceClassKey] = d->className;
    return hash;
}

Record::ConstIterator Record::begin() const
{
    return d->hash.begin();
}

Record::ConstIterator Record::end() const
{
    return d->hash.end();
}

/*
 * Param::Data
 */

Param::Data::Data(const QString &k, const QString &v) :
    key(k),
    value(v)
{

}

/*
 * Param
 */

Param::Param() :
    d(0)
{

}

Param::Param(const QString &key, const QString &value) :
    d(new Data(key, value))
{

}

bool Param::isNull() const
{
    return d == 0;
}

QString Param::key() const
{
    return isNull() ? QString() : d->key;
}

QString Param::value() const
{
    return isNull() ? QString() : d->value;
}

/*
 * Resource::Data
 */

Resource::Data::Data(const QUrl &b, const QString &r) :
    base(b),
    resource(r),
    url(base),
    followRedirects(false)
{
    setUrl();
}

void Resource::Data::setUrl()
{
    url = base;
    url.setPath(base.path() + (base.path().endsWith("/") ? "" : "/") + resource);
}

/*
 * Resource
 */

Resource::Resource(const QUrl &base, const QString &resource) :
    d(new Data(base, resource))
{

}

void Resource::setBase(const QUrl &base)
{
    d->base = base;
    d->setUrl();
}

void Resource::setResource(const QString &resource)
{
    d->resource = resource;
    d->setUrl();
}

Record Resource::find(const QVariant &id) const
{
    return find(FindOne, id.toString());
}

RecordList Resource::find(FindMulti style, const QString &from, const ParamList &params) const
{
    Q_UNUSED(style);

    QUrl url = d->url;

    foreach(Param param, params)
    {
        if(!param.isNull())
        {
            url.addQueryItem(param.key(), param.value());
        }
    }

    if(!from.isEmpty())
    {
        url.setPath(url.path() + "/" + from);
    }

    return fetch(url, d->followRedirects);
}

Record Resource::find(FindSingle style, const QString &from, const ParamList &params) const
{
    QUrl url = d->url;

    foreach(Param param, params)
    {
        if(!param.isNull())
        {
            url.addQueryItem(param.key(), param.value());
        }
    }

    if(!from.isEmpty())
    {
        url.setPath(url.path() + "/" + from);
    }

    switch(style)
    {
    case FindOne:
    case FindFirst:
    {
        RecordList results = find(FindAll, from, params);
        return results.isEmpty() ? Record() : results.front();
    }
    case FindLast:
    {
        RecordList results = find(FindAll, from, params);
        return results.isEmpty() ? Record() : results.back();
    }
    }

    return Record();
}

Record Resource::find(FindSingle style, const QString &from,
                      const Param &first, const Param &second,
                      const Param &third, const Param &fourth) const
{
    return find(style, from, ParamList() << first << second << third << fourth);
}

RecordList Resource::find(FindMulti style, const QString &from,
                          const Param &first, const Param &second,
                          const Param &third, const Param &fourth) const
{
    return find(style, from, ParamList() << first << second << third << fourth);
}

void Resource::setFollowRedirects(bool followRedirects)
{
    d->followRedirects = followRedirects;
}
<commit_msg>Seems libcurl doesn't strdup incoming streams; avoid messy buffer.<commit_after>/*
 * Copyright (C) 2010, Directed Edge, Inc. | Licensed under the MPL and LGPL
 */

#include "QActiveResource.h"
#include <QXmlStreamReader>
#include <QStringList>
#include <QDateTime>
#include <QDebug>
#include <curl/curl.h>

using namespace QActiveResource;

static const QString QActiveResourceClassKey = "QActiveResource Class";

static size_t writer(void *ptr, size_t size, size_t nmemb, void *stream)
{
    reinterpret_cast<QByteArray *>(stream)->append(QByteArray((const char *)(ptr), size * nmemb));
    return size * nmemb;
}

namespace HTTP
{
    QByteArray get(const QUrl &url, bool followRedirects = false)
    {
        QByteArray data;
        CURL *curl = curl_easy_init();

        static const int maxRetry = 1;
        int retry = 0;
        int result = 0;

        if(curl)
        {
            QByteArray encodedUrl = url.toEncoded();
            QByteArray errorBuffer(CURL_ERROR_SIZE, 0);

            do
            {
                curl_easy_setopt(curl, CURLOPT_URL, encodedUrl.data());
                curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
                curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &data);
                curl_easy_setopt(curl, CURLOPT_TIMEOUT, 25);
                curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
                curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer.data());

                if(followRedirects)
                {
                    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
                    curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1);
                    curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 2);
                }
            }
            while((result = curl_easy_perform(curl)) != 0 && ++retry <= maxRetry);

            if(result != 0)
            {
                qDebug() << "libcurl error" << result << errorBuffer << "for" << url;
            }

            curl_easy_cleanup(curl);
        }

        return data;
    }
}

static QVariant::Type lookupType(const QString &name)
{
    static QHash<QString, QVariant::Type> types;

    if(types.isEmpty())
    {
        types["integer"] = QVariant::Int;
        types["decimal"] = QVariant::Double;
        types["datetime"] = QVariant::DateTime;
        types["boolean"] = QVariant::Bool;
    }

    return types.contains(name) ? types[name] : QVariant::String;
}

static void assign(Record *record, QString name, const QVariant &value)
{
    (*record)[name.replace('-', '_')] = value;
}

static QDateTime toDateTime(const QString &s)
{
    QDateTime time = QDateTime::fromString(s.left(s.length() - 6), Qt::ISODate);

    time.setTimeSpec(Qt::UTC);

    int zoneHours = s.mid(s.length() - 6, 3).toInt();
    int zoneMinutes = s.right(2).toInt();

    return time.addSecs(-1 * (60 * zoneHours + zoneMinutes) * 60);
}

static QString toClassName(QString name)
{
    if(name.isEmpty())
    {
        return name;
    }

    name[0] = name[0].toUpper();

    QRegExp re("-([a-z])");

    while(name.indexOf(re) >= 0)
    {
        name.replace(re.cap(0), re.cap(1).toUpper());
    }

    return name;
}

static QVariant extractFromRecord(const QVariant &record)
{
    QVariantHash hash = record.toHash();
    QStringList keys = hash.keys();
    keys.removeOne(QActiveResourceClassKey);
    return hash[keys.front()];
}

static bool hasNext(const QXmlStreamReader &xml)
{
    return (xml.tokenType() == QXmlStreamReader::StartElement ||
            (xml.tokenType() == QXmlStreamReader::Characters && xml.isWhitespace()));
}

static QVariant reader(QXmlStreamReader &xml, bool advance, bool isHash)
{
    Record record;
    QString elementName;

    while(!xml.atEnd())
    {
        if(advance)
        {
            xml.readNext();
        }
        if(xml.tokenType() == QXmlStreamReader::StartElement)
        {
            if(elementName.isNull())
            {
                elementName = xml.name().toString();
            }

            QString type = xml.attributes().value("type").toString();

            if(type == "array")
            {
                QString name = xml.name().toString();
                QVariantList array;

                while(xml.readNext() && hasNext(xml))
                {
                    if(!xml.isWhitespace())
                    {
                        array.append(reader(xml, false, false));
                    }
                }

                assign(&record, name, array);
            }
            else if(xml.attributes().value("nil") == "true")
            {
                assign(&record, xml.name().toString(), QVariant());
            }
            else if((advance && xml.name() != elementName) || isHash)
            {
                QString name = xml.name().toString();

                while(xml.readNext() && xml.isWhitespace()) {}

                if(xml.tokenType() == QXmlStreamReader::StartElement)
                {
                    Record sub;
                    sub.setClassName(toClassName(name));

                    while(hasNext(xml))
                    {
                        if(!xml.isWhitespace())
                        {
                            QString subName = xml.name().toString();
                            assign(&sub, subName, extractFromRecord(reader(xml, false, true)));
                        }
                        xml.readNext();
                    }

                    assign(&record, name, sub);
                }
                else
                {
                    QVariant value;
                    QString text = xml.text().toString();

                    switch(lookupType(type))
                    {
                    case QVariant::Int:
                        value = text.toInt();
                        break;
                    case QVariant::Double:
                        value = text.toDouble();
                        break;
                    case QVariant::DateTime:
                        value = toDateTime(text);
                        break;
                    case QVariant::Bool:
                        value = bool(text == "true");
                        break;
                    default:
                        value = text.isEmpty() ? QVariant() : text;
                    }

                    assign(&record, name, value);
                }
            }
        }
        if(xml.tokenType() == QXmlStreamReader::EndElement &&
           !elementName.isNull() && elementName == xml.name())
        {
            record.setClassName(toClassName(elementName));
            return record;
        }

        advance = true;
    }

    return QVariant();
}

static RecordList fetch(QUrl url, bool followRedirects = false)
{
    if(!url.path().endsWith(".xml"))
    {
        url.setPath(url.path() + ".xml");
    }

    QByteArray data = HTTP::get(url, followRedirects);

    QXmlStreamReader xml(data);

    QVariant value = reader(xml, true, false);
    RecordList records;

    if(value.type() == QVariant::List)
    {
        foreach(QVariant v, value.toList())
        {
            records.append(v.toHash());
        }
    }
    else if(value.type() == QVariant::Hash && value.toHash().size() == 2)
    {
        foreach(QVariant v, extractFromRecord(value).toList())
        {
            records.append(v.toHash());
        }
    }
    else if(value.isValid())
    {
        records.append(value.toHash());
    }

    return records;
}

/*
 * Record
 */

Record::Record(const QVariantHash &hash) :
    d(new Data)
{
    d->hash = hash;
    d->className = d->hash.take(QActiveResourceClassKey).toString();
}

Record::Record(const QVariant &v) :
    d(new Data)
{
    d->hash = v.toHash();
    d->className = d->hash.take(QActiveResourceClassKey).toString();
}

QVariant &Record::operator[](const QString &key)
{
    return d->hash[key];
}

QVariant Record::operator[](const QString &key) const
{
    return d->hash[key];
}

bool Record::isEmpty() const
{
    return d->hash.isEmpty();
}

QString Record::className() const
{
    return d->className;
}

void Record::setClassName(const QString &name)
{
    d->className = name;
}

Record::operator QVariant() const
{
    QVariantHash hash = d->hash;
    hash[QActiveResourceClassKey] = d->className;
    return hash;
}

Record::ConstIterator Record::begin() const
{
    return d->hash.begin();
}

Record::ConstIterator Record::end() const
{
    return d->hash.end();
}

/*
 * Param::Data
 */

Param::Data::Data(const QString &k, const QString &v) :
    key(k),
    value(v)
{

}

/*
 * Param
 */

Param::Param() :
    d(0)
{

}

Param::Param(const QString &key, const QString &value) :
    d(new Data(key, value))
{

}

bool Param::isNull() const
{
    return d == 0;
}

QString Param::key() const
{
    return isNull() ? QString() : d->key;
}

QString Param::value() const
{
    return isNull() ? QString() : d->value;
}

/*
 * Resource::Data
 */

Resource::Data::Data(const QUrl &b, const QString &r) :
    base(b),
    resource(r),
    url(base),
    followRedirects(false)
{
    setUrl();
}

void Resource::Data::setUrl()
{
    url = base;
    url.setPath(base.path() + (base.path().endsWith("/") ? "" : "/") + resource);
}

/*
 * Resource
 */

Resource::Resource(const QUrl &base, const QString &resource) :
    d(new Data(base, resource))
{

}

void Resource::setBase(const QUrl &base)
{
    d->base = base;
    d->setUrl();
}

void Resource::setResource(const QString &resource)
{
    d->resource = resource;
    d->setUrl();
}

Record Resource::find(const QVariant &id) const
{
    return find(FindOne, id.toString());
}

RecordList Resource::find(FindMulti style, const QString &from, const ParamList &params) const
{
    Q_UNUSED(style);

    QUrl url = d->url;

    foreach(Param param, params)
    {
        if(!param.isNull())
        {
            url.addQueryItem(param.key(), param.value());
        }
    }

    if(!from.isEmpty())
    {
        url.setPath(url.path() + "/" + from);
    }

    return fetch(url, d->followRedirects);
}

Record Resource::find(FindSingle style, const QString &from, const ParamList &params) const
{
    QUrl url = d->url;

    foreach(Param param, params)
    {
        if(!param.isNull())
        {
            url.addQueryItem(param.key(), param.value());
        }
    }

    if(!from.isEmpty())
    {
        url.setPath(url.path() + "/" + from);
    }

    switch(style)
    {
    case FindOne:
    case FindFirst:
    {
        RecordList results = find(FindAll, from, params);
        return results.isEmpty() ? Record() : results.front();
    }
    case FindLast:
    {
        RecordList results = find(FindAll, from, params);
        return results.isEmpty() ? Record() : results.back();
    }
    }

    return Record();
}

Record Resource::find(FindSingle style, const QString &from,
                      const Param &first, const Param &second,
                      const Param &third, const Param &fourth) const
{
    return find(style, from, ParamList() << first << second << third << fourth);
}

RecordList Resource::find(FindMulti style, const QString &from,
                          const Param &first, const Param &second,
                          const Param &third, const Param &fourth) const
{
    return find(style, from, ParamList() << first << second << third << fourth);
}

void Resource::setFollowRedirects(bool followRedirects)
{
    d->followRedirects = followRedirects;
}
<|endoftext|>


<commit_before>#include "simplesp.h"
#include "spex/spcv.h"

using namespace sp;

const DotMarkerParam mrk(5, 5, 30.0);

void sample(cv::Mat &cvimg, const int key);

int main(){
    cv::VideoCapture cap(0);

    if (cap.isOpened() == false){
        printf("could not find USB camera\n");
        exit(0);
    }
    printf("'s' key : start viewtrack \n");
    printf("'ESC' key : exit \n");
    printf("\n");

    printf("option \n");
    printf("'a' key : add detected points for calibration \n");
    printf("'c' key : execute calibration (i >= 3) \n");

    int key = 0;

    // 27 = 'ESC' key
    while ((key = cv::waitKey(1)) != 27){

        // capture
        cv::Mat cvimg;
        cap >> cvimg;

        sample(cvimg, key);

        cv::imshow("viewtrack", cvimg);
    }

    cv::destroyAllWindows();
    return 0;
}

void sample(cv::Mat &cvimg, const int key){
    Mem2<Col3> img;

    // convert data type
    cvCnvImg(img, cvimg);

    // calibration
    static CalibTool ctool;
    {
        if (key == 'a') {
            ctool.addImg(mrk, img);
        }
        if (key == 'c') {
            if (ctool.execute() == true) {
                ctool.save("cam.txt");
            }
        }
    }

    const CamParam cam = (ctool.getCam() != NULL) ? *ctool.getCam() : getCamParam(img.dsize);

    static ViewTrack tracker;
    if (key == 's') {
        tracker.setView(cam, img, zeroPose());
        return;
    }

    if (tracker.getView() == NULL) return;

    tracker.execute(img);

    //if (tracker.getPose() == NULL)
    {
        if (tracker.getMask() != NULL) {
            const Mem1<bool> &mask = *tracker.getMask();
            const Mem1<Vec2> &bases = *tracker.getBases();
            const Mem1<Vec2> &crsps = *tracker.getCrsps();

            for (int i = 0; i < mask.size(); i++) {
                if (mask[i] == false) continue;

                const Vec2 pix0 = bases[i];
                const Vec2 pix1 = crsps[i];
                const Vec2 flow = pix1 - pix0;

                const double angle = (flow.x != 0.0 || flow.y != 0.0) ? ::atan2(flow.x, flow.y) : 0.0;
                const double norm = normVec(flow) / 50.0;

                Col3 col;
                cnvHSVToCol(col, getVec(angle + SP_PI, minVal(1.0, norm), 1.0));

                renderLine(img, pix0, pix1, col, 2);
            }
        }
    }

    if (tracker.getPose() != NULL) {

        const Pose base = getPose(getVec(0.0, 0.0, 20.0));

        renderAxis(img, cam, *tracker.getPose() * base, 2.0, 2);
        renderGrid3d(img, cam, *tracker.getPose() * base, 6.0, 2, getCol(100, 200, 200), 2);
    }

    cvCnvImg(cvimg, img);

}
<commit_msg>refactoring<commit_after>#include "simplesp.h"
#include "spex/spcv.h"

using namespace sp;

const DotMarkerParam mrk(5, 5, 30.0);

void sample(cv::Mat &cvimg, const int key);

int main(){
    cv::VideoCapture cap(0);

    if (cap.isOpened() == false){
        printf("could not find USB camera\n");
        exit(0);
    }
    printf("'s' key : start viewtrack \n");
    printf("'ESC' key : exit \n");
    printf("\n");

    printf("option \n");
    printf("'a' key : add detected points for calibration \n");
    printf("'c' key : execute calibration (i >= 3) \n");

    int key = 0;

    // 27 = 'ESC' key
    while ((key = cv::waitKey(1)) != 27){

        // capture
        cv::Mat cvimg;
        cap >> cvimg;

        sample(cvimg, key);

        cv::imshow("viewtrack", cvimg);
    }

    cv::destroyAllWindows();
    return 0;
}

void sample(cv::Mat &cvimg, const int key){
    Mem2<Col3> img;

    // convert data type
    cvCnvImg(img, cvimg);

    // calibration
    static CalibTool ctool;
    {
        if (key == 'a') {
            ctool.addImg(mrk, img);
        }
        if (key == 'c') {
            if (ctool.execute() == true) {
                ctool.save("cam.txt");
            }
        }
    }

    const CamParam cam = (ctool.getCam() != NULL) ? *ctool.getCam() : getCamParam(img.dsize);

    static ViewTrack tracker;
    if (key == 's') {
        tracker.setView(cam, img, zeroPose());
        return;
    }

    tracker.execute(img);

    //if (tracker.getPose() == NULL)
    {
        if (tracker.getMask() != NULL) {
            const Mem1<bool> &mask = *tracker.getMask();
            const Mem1<Vec2> &bases = *tracker.getBases();
            const Mem1<Vec2> &crsps = *tracker.getCrsps();

            for (int i = 0; i < mask.size(); i++) {
                if (mask[i] == false) continue;

                const Vec2 pix0 = bases[i];
                const Vec2 pix1 = crsps[i];
                const Vec2 flow = pix1 - pix0;

                const double angle = (flow.x != 0.0 || flow.y != 0.0) ? ::atan2(flow.x, flow.y) : 0.0;
                const double norm = normVec(flow) / 50.0;

                Col3 col;
                cnvHSVToCol(col, getVec(angle + SP_PI, minVal(1.0, norm), 1.0));

                renderLine(img, pix0, pix1, col, 2);
            }
        }
    }

    if (tracker.getPose() != NULL) {

        const Pose base = getPose(getVec(0.0, 0.0, 20.0));

        renderAxis(img, cam, *tracker.getPose() * base, 2.0, 2);
        renderGrid3d(img, cam, *tracker.getPose() * base, 6.0, 2, getCol(100, 200, 200), 2);
    }

    cvCnvImg(cvimg, img);

}
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "PolylineCompressor.h"
#include "../Util/StringUtil.h"

//TODO: return vector of start indices for each leg

void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output)
    const
{
    const unsigned end = numbers.size();
    for (unsigned i = 0; i < end; ++i)
    {
        numbers[i] <<= 1;
        if (numbers[i] < 0)
        {
            numbers[i] = ~(numbers[i]);
        }
    }
    for (const int number: numbers)
    {
        encodeNumber(number, output);
    }
}

void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output) const
{
    while (number_to_encode >= 0x20)
    {
        int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
        output += static_cast<char>(next_value);
        if (92 == next_value)
        {
            output += static_cast<char>(next_value);
        }
        number_to_encode >>= 5;
    }

    number_to_encode += 63;
    output += static_cast<char>(number_to_encode);
    if (92 == number_to_encode)
    {
        output += static_cast<char>(number_to_encode);
    }
}

JSON::String PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline) const
{
    std::string output;
    std::vector<int> delta_numbers;
    if (!polyline.empty())
    {
        FixedPointCoordinate last_coordinate = polyline[0].location;
        delta_numbers.emplace_back(last_coordinate.lat);
        delta_numbers.emplace_back(last_coordinate.lon);
        for (const auto & segment : polyline)
        {
            if (segment.necessary)
            {
                int lat_diff = segment.location.lat - last_coordinate.lat;
                int lon_diff = segment.location.lon - last_coordinate.lon;
                delta_numbers.emplace_back(lat_diff);
                delta_numbers.emplace_back(lon_diff);
                last_coordinate = segment.location;
            }
        }
        encodeVectorSignedNumber(delta_numbers, output);
    }
    JSON::String return_value(output);
    return return_value;
}

JSON::Array PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
{
    JSON::Array json_geometry_array;
    for( const auto & segment : polyline)
    {
        if (segment.necessary)
        {
            std::string tmp, output;
            FixedPointCoordinate::convertInternalLatLonToString(segment.location.lat, tmp);
            output += (tmp + ",");
            FixedPointCoordinate::convertInternalLatLonToString(segment.location.lon, tmp);
            output += tmp;
            json_geometry_array.values.push_back(output);
        }
    }
    return json_geometry_array;
}
<commit_msg>make variable const<commit_after>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "PolylineCompressor.h"
#include "../Util/StringUtil.h"

//TODO: return vector of start indices for each leg

void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output)
    const
{
    const unsigned end = numbers.size();
    for (unsigned i = 0; i < end; ++i)
    {
        numbers[i] <<= 1;
        if (numbers[i] < 0)
        {
            numbers[i] = ~(numbers[i]);
        }
    }
    for (const int number: numbers)
    {
        encodeNumber(number, output);
    }
}

void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output) const
{
    while (number_to_encode >= 0x20)
    {
        const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
        output += static_cast<char>(next_value);
        if (92 == next_value)
        {
            output += static_cast<char>(next_value);
        }
        number_to_encode >>= 5;
    }

    number_to_encode += 63;
    output += static_cast<char>(number_to_encode);
    if (92 == number_to_encode)
    {
        output += static_cast<char>(number_to_encode);
    }
}

JSON::String PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline) const
{
    std::string output;
    std::vector<int> delta_numbers;
    if (!polyline.empty())
    {
        FixedPointCoordinate last_coordinate = polyline[0].location;
        delta_numbers.emplace_back(last_coordinate.lat);
        delta_numbers.emplace_back(last_coordinate.lon);
        for (const auto & segment : polyline)
        {
            if (segment.necessary)
            {
                int lat_diff = segment.location.lat - last_coordinate.lat;
                int lon_diff = segment.location.lon - last_coordinate.lon;
                delta_numbers.emplace_back(lat_diff);
                delta_numbers.emplace_back(lon_diff);
                last_coordinate = segment.location;
            }
        }
        encodeVectorSignedNumber(delta_numbers, output);
    }
    JSON::String return_value(output);
    return return_value;
}

JSON::Array PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
{
    JSON::Array json_geometry_array;
    for( const auto & segment : polyline)
    {
        if (segment.necessary)
        {
            std::string tmp, output;
            FixedPointCoordinate::convertInternalLatLonToString(segment.location.lat, tmp);
            output += (tmp + ",");
            FixedPointCoordinate::convertInternalLatLonToString(segment.location.lon, tmp);
            output += tmp;
            json_geometry_array.values.push_back(output);
        }
    }
    return json_geometry_array;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX600 グループ・システム制御
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "RX600/system.hpp"

#ifndef F_ICLK
#  error "system_io.hpp requires F_ICLK to be defined"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  systen_io クラス
		@param[in]	BASE_CLOCK	ベース・クロック周波数（１２ＭＨｚ）
		@param[in]	EXT_CLOCK	外部クロックに入力を行う場合「true」
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t BASE_CLOCK = 12000000, bool EXT_CLOCK = false>
	struct system_io {

		static uint8_t clock_div_(uint32_t clk) noexcept
		{
			uint8_t div = 0;
			while(clk < 240000000) {
				++div;
				clk <<= 1;
			}
			return div;
		}

		//-------------------------------------------------------------//
		/*!
			@brief  システム・クロックの設定
		*/
		//-------------------------------------------------------------//
		static void setup_system_clock()
		{
			device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

			device::SYSTEM::MOSCWTCR = 9;	// 1ms wait
			// メインクロック強制発振とドライブ能力設定
			uint8_t modrv2 = 0b11;
			if(BASE_CLOCK > 20000000) modrv2 = 0b00;
			else if(BASE_CLOCK > 16000000) modrv2 = 0b01;
			else if(BASE_CLOCK > 8000000) modrv2 = 0b10;
			device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MODRV2.b(modrv2)
						  | device::SYSTEM::MOFCR.MOSEL.b(EXT_CLOCK);
///						  device::SYSTEM::MOFCR.MOFXIN.b(1)
			device::SYSTEM::MOSCCR.MOSTP = 0;		// メインクロック発振器動作
			while(device::SYSTEM::OSCOVFSR.MOOVF() == 0) { asm("nop"); }

			// RX71M、240MHz 時の MEMWAIT はスーパーバイザモードでの設定が必須なので、
			// device::SYSTEM::MEMWAIT = 1; は、start.s で設定される。

#if defined(SIG_RX65N)
			// RX65N の場合、120MHz 動作が標準
			device::SYSTEM::ROMWT = 0b10;
#endif
			// (x10.0) 0b010011, (x10.5) 0b010100, (x11.0) 0b010101, (x11.5) 0b010110
			// ... MAX x30.0
			// 内部クロックは 240MHz にする。
			uint32_t n = 240000000 * 2 / BASE_CLOCK;
			if(n < 20) n = 20;
			else if(n > 60) n = 60;
			n -= 20;
			device::SYSTEM::PLLCR.STC = n + 0b010011;  // base 240MHz(12MHz)
			device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
			while(device::SYSTEM::OSCOVFSR.PLOVF() == 0) { asm("nop"); }

			device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(clock_div_(F_FCLK))
								  | device::SYSTEM::SCKCR.ICK.b(clock_div_(F_ICLK))
								  | device::SYSTEM::SCKCR.BCK.b(clock_div_(120000000))
								  | device::SYSTEM::SCKCR.PCKA.b(clock_div_(F_PCLKA))
								  | device::SYSTEM::SCKCR.PCKB.b(clock_div_(F_PCLKB))
								  | device::SYSTEM::SCKCR.PCKC.b(clock_div_(60000000))
								  | device::SYSTEM::SCKCR.PCKD.b(clock_div_(F_PCLKD));
			device::SYSTEM::SCKCR2.UCK = 0b0100;  // USB Clock: 1/5 (120/5=24)
			device::SYSTEM::SCKCR3.CKSEL = 0b100;	///< PLL 選択

			// クロック関係書き込み不許可
			device::SYSTEM::PRCR = 0xA500;

#if defined(SIG_RX65N)
			// ROM キャッシュを有効（標準）
			device::SYSTEM::ROMCE = 1;
#endif
		}
	};

	//-------------------------------------------------------------//
	/*!
		@brief  ソフト・リセットの起動
	*/
	//-------------------------------------------------------------//
	inline void assert_soft_reset()
	{
		device::SYSTEM::PRCR = 0xA502;
		device::SYSTEM::SWRR = 0xA501;
		device::SYSTEM::PRCR = 0xA500;
	}
}
<commit_msg>update: cleanup<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX600 グループ・システム制御
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "RX600/system.hpp"

#ifndef F_ICLK
#  error "system_io.hpp requires F_ICLK to be defined"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  systen_io クラス
		@param[in]	BASE_CLOCK	ベース・クロック周波数（１２ＭＨｚ）
		@param[in]	EXT_CLOCK	外部クロックに入力を行う場合「true」
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t BASE_CLOCK = 12000000, bool EXT_CLOCK = false>
	struct system_io {

		static uint8_t clock_div_(uint32_t clk) noexcept
		{
			uint8_t div = 0;
			while(clk < 240000000) {
				++div;
				clk <<= 1;
			}
			return div;
		}

		//-------------------------------------------------------------//
		/*!
			@brief  システム・クロックの設定
		*/
		//-------------------------------------------------------------//
		static void setup_system_clock() noexcept
		{
			device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

			device::SYSTEM::MOSCWTCR = 9;	// 1ms wait
			// メインクロック強制発振とドライブ能力設定
			uint8_t modrv2 = 0b11;
			if(BASE_CLOCK > 20000000) modrv2 = 0b00;
			else if(BASE_CLOCK > 16000000) modrv2 = 0b01;
			else if(BASE_CLOCK > 8000000) modrv2 = 0b10;
			device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MODRV2.b(modrv2)
						  | device::SYSTEM::MOFCR.MOSEL.b(EXT_CLOCK);
///						  device::SYSTEM::MOFCR.MOFXIN.b(1)
			device::SYSTEM::MOSCCR.MOSTP = 0;		// メインクロック発振器動作
			while(device::SYSTEM::OSCOVFSR.MOOVF() == 0) { asm("nop"); }

			// RX71M、240MHz 時の MEMWAIT はスーパーバイザモードでの設定が必須なので、
			// device::SYSTEM::MEMWAIT = 1; は、start.s で設定される。

#if defined(SIG_RX65N)
			// RX65N の場合、120MHz 動作が標準
			device::SYSTEM::ROMWT = 0b10;
#endif
			// (x10.0) 0b010011, (x10.5) 0b010100, (x11.0) 0b010101, (x11.5) 0b010110
			// ... MAX x30.0
			// 内部クロックは 240MHz にする。
			uint32_t n = 240000000 * 2 / BASE_CLOCK;
			if(n < 20) n = 20;
			else if(n > 60) n = 60;
			n -= 20;
			device::SYSTEM::PLLCR.STC = n + 0b010011;  // base 240MHz(12MHz)
			device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
			while(device::SYSTEM::OSCOVFSR.PLOVF() == 0) { asm("nop"); }

			device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(clock_div_(F_FCLK))
								  | device::SYSTEM::SCKCR.ICK.b(clock_div_(F_ICLK))
								  | device::SYSTEM::SCKCR.BCK.b(clock_div_(120000000))
								  | device::SYSTEM::SCKCR.PCKA.b(clock_div_(F_PCLKA))
								  | device::SYSTEM::SCKCR.PCKB.b(clock_div_(F_PCLKB))
								  | device::SYSTEM::SCKCR.PCKC.b(clock_div_(60000000))
								  | device::SYSTEM::SCKCR.PCKD.b(clock_div_(F_PCLKD));
			device::SYSTEM::SCKCR2.UCK = 0b0100;  // USB Clock: 1/5 (120/5=24)
			device::SYSTEM::SCKCR3.CKSEL = 0b100;	///< PLL 選択

			// クロック関係書き込み不許可
			device::SYSTEM::PRCR = 0xA500;

#if defined(SIG_RX65N)
			// ROM キャッシュを有効（標準）
			device::SYSTEM::ROMCE = 1;
#endif
		}
	};

	//-------------------------------------------------------------//
	/*!
		@brief  ソフト・リセットの起動
	*/
	//-------------------------------------------------------------//
	inline void assert_soft_reset()
	{
		device::SYSTEM::PRCR = 0xA502;
		device::SYSTEM::SWRR = 0xA501;
		device::SYSTEM::PRCR = 0xA500;
	}
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <sal/config.h>
#include <test/unoapi_test.hxx>
#include <unotest/macros_test.hxx>
#include <rtl/strbuf.hxx>
#include <osl/file.hxx>

#include <sfx2/app.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/sfxmodelfactory.hxx>
#include <svl/intitem.hxx>
#include <com/sun/star/frame/Desktop.hpp>

#include <basic/sbxdef.hxx>

#include "docsh.hxx"
#include "patattr.hxx"
#include "scitems.hxx"
#include "document.hxx"

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

/* Implementation of Macros test */

class ScMacrosTest : public UnoApiTest
{
public:
    ScMacrosTest();

    void testStarBasic();
    void testVba();
    void testMSP();
    CPPUNIT_TEST_SUITE(ScMacrosTest);
#if !defined(MACOSX)
    //enable this test if you want to play with star basic macros in unit tests
    //works but does nothing useful yet
    CPPUNIT_TEST(testStarBasic);
    CPPUNIT_TEST(testMSP);
    CPPUNIT_TEST(testVba);
#endif

    CPPUNIT_TEST_SUITE_END();

private:
    uno::Reference<uno::XInterface> m_xCalcComponent;
};

// I suppose you could say this test doesn't really belong here, OTOH
// we need a full document to run the test ( it related originally to an
// imported Excel VBA macro ) It's convenient and fast to unit test
// this the problem this way. Perhaps in the future there will be some sort
// of slowcheck tests ( requiring a full document environment in the scripting
// module, we could move the test there then ) - relates to fdo#67547
void ScMacrosTest::testMSP()
{
    const OUString aFileNameBase("MasterScriptProviderProblem.ods");
    OUString aFileName;
    createFileURL(aFileNameBase, aFileName);
    std::cout << "MasterScriptProviderProblem (fdo#67547) test" << std::endl;
    uno::Reference< com::sun::star::lang::XComponent > xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument");

    CPPUNIT_ASSERT_MESSAGE("Failed to load MasterScriptProviderProblem.ods", xComponent.is());

    OUString aURL("vnd.sun.Star.script:Standard.Module1.TestMSP?language=Basic&location=document");
    String sUrl = aURL;
    Any aRet;
    Sequence< sal_Int16 > aOutParamIndex;
    Sequence< Any > aOutParam;
    Sequence< uno::Any > aParams;

    SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);

    CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
    ScDocShell* xDocSh = static_cast<ScDocShell*>(pFoundShell);

    pFoundShell->CallXScript(xComponent, sUrl, aParams, aRet, aOutParamIndex,aOutParam);
    OUString sResult;
    aRet >>= sResult;

    std::cout << "Result is " << sResult << std::endl;
    CPPUNIT_ASSERT_MESSAGE("TestMSP ( for fdo#67547) failed", sResult == "OK" );
    xDocSh->DoClose();
}

void ScMacrosTest::testStarBasic()
{
    const OUString aFileNameBase("StarBasic.ods");
    OUString aFileName;
    createFileURL(aFileNameBase, aFileName);
    std::cout << "StarBasic test" << std::endl;
    uno::Reference< com::sun::star::lang::XComponent > xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument");

    CPPUNIT_ASSERT_MESSAGE("Failed to load StarBasic.ods", xComponent.is());

    OUString aURL("vnd.sun.Star.script:Standard.Module1.Macro1?language=Basic&location=document");
    String sUrl = aURL;
    Any aRet;
    Sequence< sal_Int16 > aOutParamIndex;
    Sequence< Any > aOutParam;
    Sequence< uno::Any > aParams;

    SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);

    CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
    ScDocShell* xDocSh = static_cast<ScDocShell*>(pFoundShell);
    ScDocument* pDoc = xDocSh->GetDocument();

    pFoundShell->CallXScript(xComponent, sUrl, aParams, aRet, aOutParamIndex,aOutParam);
    double aValue;
    pDoc->GetValue(0,0,0,aValue);
    std::cout << "returned value = " << aValue << std::endl;
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("script did not change the value of Sheet1.A1",2.0, aValue, 0.00001);
    xDocSh->DoClose();
}

void ScMacrosTest::testVba()
{
    TestMacroInfo testInfo[] = {
        {
            OUString("TestAddress."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("vba."),
            OUString("vnd.sun.Star.script:VBAProject.Modul1.Modul1?language=Basic&location=document"),
        },
        {
            OUString("MiscRangeTests."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("bytearraystring."),
            OUString("vnd.sun.Star.script:VBAProject.testMacro.test?language=Basic&location=document")
        },
        {
            OUString("AutoFilter."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("CalcFont."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("TestIntersection."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("TestUnion."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("range-4."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Ranges-3."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("TestCalc_Rangetest."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("TestCalc_Rangetest2."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Ranges-2."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("pagesetup."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Window."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("window2."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("PageBreaks."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Shapes."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
#if 0 // TODO : fix this
        {
            OUString("Ranges."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
#endif
        {
            OUString("CheckOptionToggleValue."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("GeneratedEventTest."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("MiscControlTests."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Workbooks."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Names."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
    };
    OUString sTempDir;
    OUString sTempDirURL;
    osl::FileBase:: getTempDirURL( sTempDirURL );
    osl::FileBase::getSystemPathFromFileURL( sTempDirURL, sTempDir );
    sTempDir += OUString( SAL_PATHDELIMITER );
    OUString sTestFileName("My Test WorkBook.xls");
    Sequence< uno::Any > aParams;
    for ( sal_uInt32  i=0; i<SAL_N_ELEMENTS( testInfo ); ++i )
    {
        OUString aFileName;
        createFileURL(testInfo[i].sFileBaseName + "xls", aFileName);
        uno::Reference< com::sun::star::lang::XComponent > xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument");
        OUString sMsg( "Failed to load " + aFileName );
        CPPUNIT_ASSERT_MESSAGE( OUStringToOString( sMsg, RTL_TEXTENCODING_UTF8 ).getStr(), xComponent.is() );

        String sUrl = testInfo[i].sMacroUrl;
        Any aRet;
        Sequence< sal_Int16 > aOutParamIndex;
        Sequence< Any > aOutParam;
        bool bWorkbooksHandling = OUString( testInfo[i].sFileBaseName ).equalsAscii("Workbooks.") && !sTempDir.isEmpty() ;

        if ( bWorkbooksHandling )
        {
            aParams.realloc(2);
            aParams[ 0 ] <<= sTempDir;
            aParams[ 1 ] <<= sTestFileName;
        }

        SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);

        CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
        std::cout << "about to invoke vba test in " << OUStringToOString( aFileName, RTL_TEXTENCODING_UTF8 ).getStr() << std::endl;

        pFoundShell->CallXScript(xComponent, sUrl, aParams, aRet, aOutParamIndex,aOutParam);
        OUString aStringRes;
        aRet >>= aStringRes;
        std::cout << "value of Ret " << OUStringToOString( aStringRes, RTL_TEXTENCODING_UTF8 ).getStr() << std::endl;
        CPPUNIT_ASSERT_MESSAGE( "script reported failure",aStringRes == "OK" );
        pFoundShell->DoClose();
        if ( bWorkbooksHandling )
        {
            OUString sFileUrl;
            OUString sFilePath = sTempDir + sTestFileName;
            osl::FileBase::getFileURLFromSystemPath( sFilePath, sFileUrl );
            if ( !sFileUrl.isEmpty() )
                osl::File::remove( sFileUrl );
        }
    }
}

ScMacrosTest::ScMacrosTest()
      : UnoApiTest("/sc/qa/extras/testdocuments")
{
}

CPPUNIT_TEST_SUITE_REGISTRATION(ScMacrosTest);

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>WaE: unused variables<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <sal/config.h>
#include <test/unoapi_test.hxx>
#include <unotest/macros_test.hxx>
#include <rtl/strbuf.hxx>
#include <osl/file.hxx>

#include <sfx2/app.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/sfxmodelfactory.hxx>
#include <svl/intitem.hxx>
#include <com/sun/star/frame/Desktop.hpp>

#include <basic/sbxdef.hxx>

#include "docsh.hxx"
#include "patattr.hxx"
#include "scitems.hxx"
#include "document.hxx"

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

/* Implementation of Macros test */

class ScMacrosTest : public UnoApiTest
{
public:
    ScMacrosTest();

    void testStarBasic();
    void testVba();
    void testMSP();
    CPPUNIT_TEST_SUITE(ScMacrosTest);
#if !defined(MACOSX)
    //enable this test if you want to play with star basic macros in unit tests
    //works but does nothing useful yet
    CPPUNIT_TEST(testStarBasic);
    CPPUNIT_TEST(testMSP);
    CPPUNIT_TEST(testVba);
#endif

    CPPUNIT_TEST_SUITE_END();

private:
    uno::Reference<uno::XInterface> m_xCalcComponent;
};

// I suppose you could say this test doesn't really belong here, OTOH
// we need a full document to run the test ( it related originally to an
// imported Excel VBA macro ) It's convenient and fast to unit test
// this the problem this way. Perhaps in the future there will be some sort
// of slowcheck tests ( requiring a full document environment in the scripting
// module, we could move the test there then ) - relates to fdo#67547
void ScMacrosTest::testMSP()
{
    const OUString aFileNameBase("MasterScriptProviderProblem.ods");
    OUString aFileName;
    createFileURL(aFileNameBase, aFileName);
    std::cout << "MasterScriptProviderProblem (fdo#67547) test" << std::endl;
    uno::Reference< com::sun::star::lang::XComponent > xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument");

    CPPUNIT_ASSERT_MESSAGE("Failed to load MasterScriptProviderProblem.ods", xComponent.is());

    OUString aURL("vnd.sun.Star.script:Standard.Module1.TestMSP?language=Basic&location=document");
    String sUrl = aURL;
    Any aRet;
    Sequence< sal_Int16 > aOutParamIndex;
    Sequence< Any > aOutParam;
    Sequence< uno::Any > aParams;

    SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
    CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);

    pFoundShell->CallXScript(xComponent, sUrl, aParams, aRet, aOutParamIndex,aOutParam);
    OUString sResult;
    aRet >>= sResult;

    std::cout << "Result is " << sResult << std::endl;
    CPPUNIT_ASSERT_MESSAGE("TestMSP ( for fdo#67547) failed", sResult == "OK" );
    xDocSh->DoClose();
}

void ScMacrosTest::testStarBasic()
{
    const OUString aFileNameBase("StarBasic.ods");
    OUString aFileName;
    createFileURL(aFileNameBase, aFileName);
    std::cout << "StarBasic test" << std::endl;
    uno::Reference< com::sun::star::lang::XComponent > xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument");

    CPPUNIT_ASSERT_MESSAGE("Failed to load StarBasic.ods", xComponent.is());

    OUString aURL("vnd.sun.Star.script:Standard.Module1.Macro1?language=Basic&location=document");
    String sUrl = aURL;
    Any aRet;
    Sequence< sal_Int16 > aOutParamIndex;
    Sequence< Any > aOutParam;
    Sequence< uno::Any > aParams;

    SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);

    CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
    ScDocShell* xDocSh = static_cast<ScDocShell*>(pFoundShell);
    ScDocument* pDoc = xDocSh->GetDocument();

    pFoundShell->CallXScript(xComponent, sUrl, aParams, aRet, aOutParamIndex,aOutParam);
    double aValue;
    pDoc->GetValue(0,0,0,aValue);
    std::cout << "returned value = " << aValue << std::endl;
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("script did not change the value of Sheet1.A1",2.0, aValue, 0.00001);
    xDocSh->DoClose();
}

void ScMacrosTest::testVba()
{
    TestMacroInfo testInfo[] = {
        {
            OUString("TestAddress."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("vba."),
            OUString("vnd.sun.Star.script:VBAProject.Modul1.Modul1?language=Basic&location=document"),
        },
        {
            OUString("MiscRangeTests."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("bytearraystring."),
            OUString("vnd.sun.Star.script:VBAProject.testMacro.test?language=Basic&location=document")
        },
        {
            OUString("AutoFilter."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("CalcFont."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("TestIntersection."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("TestUnion."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("range-4."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Ranges-3."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("TestCalc_Rangetest."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("TestCalc_Rangetest2."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Ranges-2."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("pagesetup."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Window."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("window2."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("PageBreaks."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Shapes."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
#if 0 // TODO : fix this
        {
            OUString("Ranges."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
#endif
        {
            OUString("CheckOptionToggleValue."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("GeneratedEventTest."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("MiscControlTests."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Workbooks."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
        {
            OUString("Names."),
            OUString("vnd.sun.Star.script:VBAProject.testMacros.test?language=Basic&location=document")
        },
    };
    OUString sTempDir;
    OUString sTempDirURL;
    osl::FileBase:: getTempDirURL( sTempDirURL );
    osl::FileBase::getSystemPathFromFileURL( sTempDirURL, sTempDir );
    sTempDir += OUString( SAL_PATHDELIMITER );
    OUString sTestFileName("My Test WorkBook.xls");
    Sequence< uno::Any > aParams;
    for ( sal_uInt32  i=0; i<SAL_N_ELEMENTS( testInfo ); ++i )
    {
        OUString aFileName;
        createFileURL(testInfo[i].sFileBaseName + "xls", aFileName);
        uno::Reference< com::sun::star::lang::XComponent > xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument");
        OUString sMsg( "Failed to load " + aFileName );
        CPPUNIT_ASSERT_MESSAGE( OUStringToOString( sMsg, RTL_TEXTENCODING_UTF8 ).getStr(), xComponent.is() );

        String sUrl = testInfo[i].sMacroUrl;
        Any aRet;
        Sequence< sal_Int16 > aOutParamIndex;
        Sequence< Any > aOutParam;
        bool bWorkbooksHandling = OUString( testInfo[i].sFileBaseName ).equalsAscii("Workbooks.") && !sTempDir.isEmpty() ;

        if ( bWorkbooksHandling )
        {
            aParams.realloc(2);
            aParams[ 0 ] <<= sTempDir;
            aParams[ 1 ] <<= sTestFileName;
        }

        SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);

        CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
        std::cout << "about to invoke vba test in " << OUStringToOString( aFileName, RTL_TEXTENCODING_UTF8 ).getStr() << std::endl;

        pFoundShell->CallXScript(xComponent, sUrl, aParams, aRet, aOutParamIndex,aOutParam);
        OUString aStringRes;
        aRet >>= aStringRes;
        std::cout << "value of Ret " << OUStringToOString( aStringRes, RTL_TEXTENCODING_UTF8 ).getStr() << std::endl;
        CPPUNIT_ASSERT_MESSAGE( "script reported failure",aStringRes == "OK" );
        pFoundShell->DoClose();
        if ( bWorkbooksHandling )
        {
            OUString sFileUrl;
            OUString sFilePath = sTempDir + sTestFileName;
            osl::FileBase::getFileURLFromSystemPath( sFilePath, sFileUrl );
            if ( !sFileUrl.isEmpty() )
                osl::File::remove( sFileUrl );
        }
    }
}

ScMacrosTest::ScMacrosTest()
      : UnoApiTest("/sc/qa/extras/testdocuments")
{
}

CPPUNIT_TEST_SUITE_REGISTRATION(ScMacrosTest);

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>