<commit_before>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/Win32/HardwareInfoImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <windows.h>

#ifdef NAZARA_COMPILER_MSVC
	#include <intrin.h>
#endif

#include <Nazara/Core/Debug.hpp>

namespace Nz
{
	void HardwareInfoImpl::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4])
	{
	#if defined(NAZARA_COMPILER_MSVC)
		static_assert(sizeof(UInt32) == sizeof(int), "Assertion failed");

		// Visual propose une fonction intrinsèque pour le cpuid
		__cpuidex(reinterpret_cast<int*>(registers), static_cast<int>(functionId), static_cast<int>(subFunctionId));
	#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
		// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
		asm volatile ("cpuid" // Besoin d'être volatile ?
					  : "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
					  : "a" (functionId), "c" (subFunctionId));                                // input
	#else
		NazaraInternalError("Cpuid has been called although it is not supported");
	#endif
	}

	unsigned int HardwareInfoImpl::GetProcessorCount()
	{
		// Plus simple (et plus portable) que de passer par le CPUID
		SYSTEM_INFO infos;
		GetNativeSystemInfo(&infos);

		return infos.dwNumberOfProcessors;
	}

	UInt64 HardwareInfoImpl::GetTotalMemory()
	{
		MEMORYSTATUSEX memStatus;
		memStatus.dwLength = sizeof(memStatus);
		GlobalMemoryStatusEx(&memStatus);

		return memStatus.ullTotalPhys;
	}

	bool HardwareInfoImpl::IsCpuidSupported()
	{
	#ifdef NAZARA_PLATFORM_x64
		return true; // Toujours supporté sur un processeur 64 bits
	#else
		#if defined(NAZARA_COMPILER_MSVC)
		int supported;
		__asm
		{
			pushfd
			pop  eax
			mov  ecx, eax
			xor  eax, 0x200000
			push eax
			popfd
			pushfd
			pop  eax
			xor  eax, ecx
			mov  supported, eax
			push ecx
			popfd
		};

		return supported != 0;
		#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
		int supported;
		asm volatile (" pushfl\n"
					  " pop %%eax\n"
					  " mov %%eax, %%ecx\n"
					  " xor $0x200000, %%eax\n"
					  " push %%eax\n"
					  " popfl\n"
					  " pushfl\n"
					  " pop %%eax\n"
					  " xor %%ecx, %%eax\n"
					  " mov %%eax, %0\n"
					  " push %%ecx\n"
					  " popfl"
					  : "=m" (supported)         // output
					  :                          // input
					  : "eax", "ecx", "memory"); // clobbered register

		return supported != 0;
		#else
		return false;
		#endif
	#endif
}
}
<commit_msg>Core/HardwareInfo: Fix indentation (Windows)<commit_after>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/Win32/HardwareInfoImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <windows.h>

#ifdef NAZARA_COMPILER_MSVC
	#include <intrin.h>
#endif

#include <Nazara/Core/Debug.hpp>

namespace Nz
{
	void HardwareInfoImpl::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4])
	{
	#if defined(NAZARA_COMPILER_MSVC)
		static_assert(sizeof(UInt32) == sizeof(int), "Assertion failed");

		// Visual propose une fonction intrinsèque pour le cpuid
		__cpuidex(reinterpret_cast<int*>(registers), static_cast<int>(functionId), static_cast<int>(subFunctionId));
	#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
		// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
		asm volatile ("cpuid" // Besoin d'être volatile ?
					  : "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
					  : "a" (functionId), "c" (subFunctionId));                                // input
	#else
		NazaraInternalError("Cpuid has been called although it is not supported");
	#endif
	}

	unsigned int HardwareInfoImpl::GetProcessorCount()
	{
		// Plus simple (et plus portable) que de passer par le CPUID
		SYSTEM_INFO infos;
		GetNativeSystemInfo(&infos);

		return infos.dwNumberOfProcessors;
	}

	UInt64 HardwareInfoImpl::GetTotalMemory()
	{
		MEMORYSTATUSEX memStatus;
		memStatus.dwLength = sizeof(memStatus);
		GlobalMemoryStatusEx(&memStatus);

		return memStatus.ullTotalPhys;
	}

	bool HardwareInfoImpl::IsCpuidSupported()
	{
	#ifdef NAZARA_PLATFORM_x64
		return true; // Toujours supporté sur un processeur 64 bits
	#else
		#if defined(NAZARA_COMPILER_MSVC)
		int supported;
		__asm
		{
			pushfd
			pop  eax
			mov  ecx, eax
			xor  eax, 0x200000
			push eax
			popfd
			pushfd
			pop  eax
			xor  eax, ecx
			mov  supported, eax
			push ecx
			popfd
		};

		return supported != 0;
		#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
		int supported;
		asm volatile (" pushfl\n"
		              " pop %%eax\n"
		              " mov %%eax, %%ecx\n"
		              " xor $0x200000, %%eax\n"
		              " push %%eax\n"
		              " popfl\n"
		              " pushfl\n"
		              " pop %%eax\n"
		              " xor %%ecx, %%eax\n"
		              " mov %%eax, %0\n"
		              " push %%ecx\n"
		              " popfl"
		              : "=m" (supported)         // output
		              :                          // input
		              : "eax", "ecx", "memory"); // clobbered register

		return supported != 0;
		#else
		return false;
		#endif
	#endif
	}
}
<|endoftext|>


<commit_before>/* ========================================================================= *
 *                                                                           *
 *                               OpenMesh                                    *
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openmesh.org                               *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenMesh.                                            *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * 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 of the copyright holder 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 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.              *
 *                                                                           *
 * ========================================================================= */

/*===========================================================================*\
 *                                                                           *
 *   $Revision$                                                              *
 *   $Date$                                                                  *
 *                                                                           *
\*===========================================================================*/

#ifndef PROPERTYMANAGER_HH_
#define PROPERTYMANAGER_HH_

#include <sstream>
#include <stdexcept>
#include <string>

namespace OpenMesh {

/**
 * This class is intended to manage the lifecycle of properties.
 * It also defines convenience operators to access the encapsulated
 * property's value.
 *
 * Usage example:
 *
 * \code
 * TriMesh mesh;
 * PropertyManager<VPropHandleT<bool>, TriMesh> visited(mesh, "visited.plugin-example.i8.informatik.rwth-aachen.de");
 *
 * for (TriMesh::VertexIter vh_it = mesh.begin(); ... ; ...) {
 *     if (!visited[*vh_it]) {
 *         visitComponent(mesh, *vh_it, visited);
 *     }
 * }
 * \endcode
 *
 */
template<typename PROPTYPE, typename MeshT>
class PropertyManager {
#if __cplusplus > 199711L or __GXX_EXPERIMENTAL_CXX0X__
    public:
        PropertyManager(const PropertyManager&) = delete;
        PropertyManager& operator=(const PropertyManager&) = delete;
#else
    private:
        /**
         * Noncopyable because there aren't no straightforward copy semantics.
         */
        PropertyManager(const PropertyManager&);

        /**
         * Noncopyable because there aren't no straightforward copy semantics.
         */
        PropertyManager& operator=(const PropertyManager&);
#endif

    public:
        /**
         * Constructor.
         *
         * Throws an \p std::runtime_error if \p existing is true and
         * no property named \p propname of the appropriate property type
         * exists.
         *
         * @param mesh The mesh on which to create the property.
         * @param propname The name of the property.
         * @param existing If false, a new property is created and its lifecycle is managed (i.e.
         * the property is deleted upon destruction of the PropertyManager instance). If true,
         * the instance merely acts as a convenience wrapper around an existing property with no
         * lifecycle management whatsoever.
         */
        PropertyManager(MeshT &mesh, const char *propname, bool existing = false) : mesh_(&mesh), retain_(existing), name_(propname) {
            if (existing) {
                if (!mesh_->get_property_handle(prop_, propname)) {
                    std::ostringstream oss;
                    oss << "Requested property handle \"" << propname << "\" does not exist.";
                    throw std::runtime_error(oss.str());
                }
            } else {
                mesh_->add_property(prop_, propname);
            }
        }

        PropertyManager() : mesh_(0), retain_(false) {
        }

        ~PropertyManager() {
            deleteProperty();
        }

        void swap(PropertyManager &rhs) {
            std::swap(mesh_, rhs.mesh_);
            std::swap(prop_, rhs.prop_);
            std::swap(retain_, rhs.retain_);
            std::swap(name_, rhs.name_);
        }

        static bool propertyExists(MeshT &mesh, const char *propname) {
            PROPTYPE dummy;
            return mesh.get_property_handle(dummy, propname);
        }

        bool isValid() const { return mesh_ != 0; }
        operator bool() const { return isValid(); }

        const PROPTYPE &getRawProperty() const { return prop_; }

        const std::string &getName() const { return name_; }

        MeshT &getMesh() const { return *mesh_; }

#if __cplusplus > 199711L or __GXX_EXPERIMENTAL_CXX0X__
        /**
         * Move constructor. Transfers ownership (delete responsibility).
         */
        PropertyManager(PropertyManager &&rhs) : mesh_(rhs.mesh_), prop_(rhs.prop_), retain_(rhs.retain_), name_(rhs.name_) {
            rhs.retain_ = true;
        }

        /**
         * Move assignment. Transfers ownership (delete responsibility).
         */
        PropertyManager &operator=(PropertyManager &&rhs) {

            deleteProperty();

            mesh_ = rhs.mesh_;
            prop_ = rhs.prop_;
            retain_ = rhs.retain_;
            name_ = rhs.name_;
            rhs.retain_ = true;

            return *this;
        }

        /**
         * Create a property manager for the supplied property and mesh.
         * If the property doesn't exist, it is created. In any case,
         * lifecycle management is disabled.
         */
        static PropertyManager createIfNotExists(MeshT &mesh, const char *propname) {
            PROPTYPE dummy_prop;
            PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
            pm.retain();
            return std::move(pm);
        }

        PropertyManager duplicate(const char *clone_name) {
            PropertyManager pm(*mesh_, clone_name, false);
            pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
            return std::move(pm);
        }

        /**
         * Included for backwards compatibility with non-C++11 version.
         */
        PropertyManager move() {
            return std::move(*this);
        }

#else
        class Proxy {
            private:
                Proxy(MeshT *mesh_, PROPTYPE prop_, bool retain_, const std::string &name_) :
                    mesh_(mesh_), prop_(prop_), retain_(retain_), name_(name_) {}
                MeshT *mesh_;
                PROPTYPE prop_;
                bool retain_;
                std::string name_;

                friend class PropertyManager;
        };

        operator Proxy() {
            Proxy p(mesh_, prop_, retain_, name_);
            mesh_ = 0;
            retain_ = true;
            return p;
        }

        Proxy move() {
            return (Proxy)*this;
        }

        PropertyManager(Proxy p) : mesh_(p.mesh_), prop_(p.prop_), retain_(p.retain_), name_(p.name_) {}

        PropertyManager &operator=(Proxy p) {
            PropertyManager(p).swap(*this);
            return *this;
        }

        /**
         * Create a property manager for the supplied property and mesh.
         * If the property doesn't exist, it is created. In any case,
         * lifecycle management is disabled.
         */
        static Proxy createIfNotExists(MeshT &mesh, const char *propname) {
            PROPTYPE dummy_prop;
            PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
            pm.retain();
            return (Proxy)pm;
        }

        Proxy duplicate(const char *clone_name) {
            PropertyManager pm(*mesh_, clone_name, false);
            pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
            return (Proxy)pm;
        }
#endif

        /**
         * \brief Disable lifecycle management for this property.
         *
         * If this method is called, the encapsulated property will not be deleted
         * upon destruction of the PropertyManager instance.
         */
        inline void retain(bool doRetain = true) {
            retain_ = doRetain;
        }

        /**
         * Access the encapsulated property.
         */
        inline PROPTYPE &operator* () {
            return prop_;
        }

        /**
         * Access the encapsulated property.
         */
        inline const PROPTYPE &operator* () const {
            return prop_;
        }

        /**
         * Enables convenient access to the encapsulated property.
         *
         * For a usage example see this class' documentation.
         *
         * @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
         */
        template<typename HandleType>
        inline typename PROPTYPE::reference operator[] (const HandleType &handle) {
            return mesh_->property(prop_, handle);
        }

        /**
         * Enables convenient access to the encapsulated property.
         *
         * For a usage example see this class' documentation.
         *
         * @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
         */
        template<typename HandleType>
        inline typename PROPTYPE::const_reference operator[] (const HandleType &handle) const {
            return mesh_->property(prop_, handle);
        }

        /**
         * Conveniently set the property for an entire range of values.
         *
         * Examples:
         * \code
         * MeshT mesh;
         * PropertyManager<VPropHandleT<double>, MeshT> distance(
         *     mesh, "distance.plugin-example.i8.informatik.rwth-aachen.de");
         * distance.set_range(
         *     mesh.vertices_begin(), mesh.vertices_end(),
         *     std::numeric_limits<double>::infinity());
         * \endcode
         * or
         * \code
         * MeshT::VertexHandle vh;
         * distance.set_range(
         *     mesh.vv_begin(vh), mesh.vv_end(vh),
         *     std::numeric_limits<double>::infinity());
         * \endcode
         *
         * @param begin Start iterator. Needs to dereference to HandleType.
         * @param end End iterator. (Exclusive.)
         * @param value The value the range will be set to.
         */
        template<typename HandleTypeIterator>
        void set_range(HandleTypeIterator begin, HandleTypeIterator end,
                typename PROPTYPE::const_reference value) {
            for (; begin != end; ++begin)
                (*this)[*begin] = value;
        }

        /**
         * Conveniently transfer the values managed by one property manager
         * onto the values managed by a different property manager.
         *
         * @param begin Start iterator. Needs to dereference to HandleType. Will
         * be used with this property manager.
         * @param end End iterator. (Exclusive.) Will be used with this property
         * manager.
         * @param dst_propmanager The destination property manager.
         * @param dst_begin Start iterator. Needs to dereference to the
         * HandleType of dst_propmanager. Will be used with dst_propmanager.
         * @param dst_end End iterator. (Exclusive.)
         * Will be used with dst_propmanager. Used to double check the bounds.
         */
        template<typename HandleTypeIterator, typename PROPTYPE_2,
                 typename MeshT_2, typename HandleTypeIterator_2>
        void copy_to(HandleTypeIterator begin, HandleTypeIterator end,
                PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
                HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const {

            for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) {
                dst_propmanager[*dst_begin] = (*this)[*begin];
            }
        }

        template<typename RangeType, typename PROPTYPE_2,
                 typename MeshT_2, typename RangeType_2>
        void copy_to(const RangeType &range,
                PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
                const RangeType_2 &dst_range) const {
            copy_to(range.begin(), range.end(), dst_propmanager,
                    dst_range.begin(), dst_range.end());
        }

        /**
         * Copy the values of a property from a source range to
         * a target range. The source range must not be smaller than the
         * target range.
         *
         * @param prop_name Name of the property to copy. Must exist on the
         * source mesh. Will be created on the target mesh if it doesn't exist.
         *
         * @param src_mesh Source mesh from which to copy.
         * @param src_range Source range which to copy. Must not be smaller than
         * dst_range.
         * @param dst_mesh Destination mesh on which to copy.
         * @param dst_range Destination range.
         */
        template<typename RangeType, typename MeshT_2, typename RangeType_2>
        static void copy(const char *prop_name,
                MeshT &src_mesh, const RangeType &src_range,
                MeshT_2 &dst_mesh, const RangeType_2 &dst_range) {

            typedef OpenMesh::PropertyManager<PROPTYPE, MeshT> DstPM;
            DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));

            typedef OpenMesh::PropertyManager<PROPTYPE, MeshT_2> SrcPM;
            SrcPM src(src_mesh, prop_name, true);

            src.copy_to(src_range, dst, dst_range);
        }

    private:
        void deleteProperty() {
            if (!retain_)
                mesh_->remove_property(prop_);
        }

    private:
        MeshT *mesh_;
        PROPTYPE prop_;
        bool retain_;
        std::string name_;
};

} /* namespace OpenMesh */
#endif /* PROPERTYMANAGER_HH_ */
<commit_msg>Fixing PropertyManager so that it cooperates with bool properties even on unforgiving implementations (such as clang).<commit_after>/* ========================================================================= *
 *                                                                           *
 *                               OpenMesh                                    *
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openmesh.org                               *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenMesh.                                            *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * 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 of the copyright holder 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 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.              *
 *                                                                           *
 * ========================================================================= */

/*===========================================================================*\
 *                                                                           *
 *   $Revision$                                                              *
 *   $Date$                                                                  *
 *                                                                           *
\*===========================================================================*/

#ifndef PROPERTYMANAGER_HH_
#define PROPERTYMANAGER_HH_

#include <sstream>
#include <stdexcept>
#include <string>

namespace OpenMesh {

/**
 * This class is intended to manage the lifecycle of properties.
 * It also defines convenience operators to access the encapsulated
 * property's value.
 *
 * Usage example:
 *
 * \code
 * TriMesh mesh;
 * PropertyManager<VPropHandleT<bool>, TriMesh> visited(mesh, "visited.plugin-example.i8.informatik.rwth-aachen.de");
 *
 * for (TriMesh::VertexIter vh_it = mesh.begin(); ... ; ...) {
 *     if (!visited[*vh_it]) {
 *         visitComponent(mesh, *vh_it, visited);
 *     }
 * }
 * \endcode
 *
 */
template<typename PROPTYPE, typename MeshT>
class PropertyManager {
#if __cplusplus > 199711L or __GXX_EXPERIMENTAL_CXX0X__
    public:
        PropertyManager(const PropertyManager&) = delete;
        PropertyManager& operator=(const PropertyManager&) = delete;
#else
    private:
        /**
         * Noncopyable because there aren't no straightforward copy semantics.
         */
        PropertyManager(const PropertyManager&);

        /**
         * Noncopyable because there aren't no straightforward copy semantics.
         */
        PropertyManager& operator=(const PropertyManager&);
#endif

    public:
        /**
         * Constructor.
         *
         * Throws an \p std::runtime_error if \p existing is true and
         * no property named \p propname of the appropriate property type
         * exists.
         *
         * @param mesh The mesh on which to create the property.
         * @param propname The name of the property.
         * @param existing If false, a new property is created and its lifecycle is managed (i.e.
         * the property is deleted upon destruction of the PropertyManager instance). If true,
         * the instance merely acts as a convenience wrapper around an existing property with no
         * lifecycle management whatsoever.
         */
        PropertyManager(MeshT &mesh, const char *propname, bool existing = false) : mesh_(&mesh), retain_(existing), name_(propname) {
            if (existing) {
                if (!mesh_->get_property_handle(prop_, propname)) {
                    std::ostringstream oss;
                    oss << "Requested property handle \"" << propname << "\" does not exist.";
                    throw std::runtime_error(oss.str());
                }
            } else {
                mesh_->add_property(prop_, propname);
            }
        }

        PropertyManager() : mesh_(0), retain_(false) {
        }

        ~PropertyManager() {
            deleteProperty();
        }

        void swap(PropertyManager &rhs) {
            std::swap(mesh_, rhs.mesh_);
            std::swap(prop_, rhs.prop_);
            std::swap(retain_, rhs.retain_);
            std::swap(name_, rhs.name_);
        }

        static bool propertyExists(MeshT &mesh, const char *propname) {
            PROPTYPE dummy;
            return mesh.get_property_handle(dummy, propname);
        }

        bool isValid() const { return mesh_ != 0; }
        operator bool() const { return isValid(); }

        const PROPTYPE &getRawProperty() const { return prop_; }

        const std::string &getName() const { return name_; }

        MeshT &getMesh() const { return *mesh_; }

#if __cplusplus > 199711L or __GXX_EXPERIMENTAL_CXX0X__
        /**
         * Move constructor. Transfers ownership (delete responsibility).
         */
        PropertyManager(PropertyManager &&rhs) : mesh_(rhs.mesh_), prop_(rhs.prop_), retain_(rhs.retain_), name_(rhs.name_) {
            rhs.retain_ = true;
        }

        /**
         * Move assignment. Transfers ownership (delete responsibility).
         */
        PropertyManager &operator=(PropertyManager &&rhs) {

            deleteProperty();

            mesh_ = rhs.mesh_;
            prop_ = rhs.prop_;
            retain_ = rhs.retain_;
            name_ = rhs.name_;
            rhs.retain_ = true;

            return *this;
        }

        /**
         * Create a property manager for the supplied property and mesh.
         * If the property doesn't exist, it is created. In any case,
         * lifecycle management is disabled.
         */
        static PropertyManager createIfNotExists(MeshT &mesh, const char *propname) {
            PROPTYPE dummy_prop;
            PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
            pm.retain();
            return std::move(pm);
        }

        PropertyManager duplicate(const char *clone_name) {
            PropertyManager pm(*mesh_, clone_name, false);
            pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
            return std::move(pm);
        }

        /**
         * Included for backwards compatibility with non-C++11 version.
         */
        PropertyManager move() {
            return std::move(*this);
        }

#else
        class Proxy {
            private:
                Proxy(MeshT *mesh_, PROPTYPE prop_, bool retain_, const std::string &name_) :
                    mesh_(mesh_), prop_(prop_), retain_(retain_), name_(name_) {}
                MeshT *mesh_;
                PROPTYPE prop_;
                bool retain_;
                std::string name_;

                friend class PropertyManager;
        };

        operator Proxy() {
            Proxy p(mesh_, prop_, retain_, name_);
            mesh_ = 0;
            retain_ = true;
            return p;
        }

        Proxy move() {
            return (Proxy)*this;
        }

        PropertyManager(Proxy p) : mesh_(p.mesh_), prop_(p.prop_), retain_(p.retain_), name_(p.name_) {}

        PropertyManager &operator=(Proxy p) {
            PropertyManager(p).swap(*this);
            return *this;
        }

        /**
         * Create a property manager for the supplied property and mesh.
         * If the property doesn't exist, it is created. In any case,
         * lifecycle management is disabled.
         */
        static Proxy createIfNotExists(MeshT &mesh, const char *propname) {
            PROPTYPE dummy_prop;
            PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
            pm.retain();
            return (Proxy)pm;
        }

        Proxy duplicate(const char *clone_name) {
            PropertyManager pm(*mesh_, clone_name, false);
            pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
            return (Proxy)pm;
        }
#endif

        /**
         * \brief Disable lifecycle management for this property.
         *
         * If this method is called, the encapsulated property will not be deleted
         * upon destruction of the PropertyManager instance.
         */
        inline void retain(bool doRetain = true) {
            retain_ = doRetain;
        }

        /**
         * Access the encapsulated property.
         */
        inline PROPTYPE &operator* () {
            return prop_;
        }

        /**
         * Access the encapsulated property.
         */
        inline const PROPTYPE &operator* () const {
            return prop_;
        }

        /**
         * Enables convenient access to the encapsulated property.
         *
         * For a usage example see this class' documentation.
         *
         * @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
         */
        template<typename HandleType>
        inline typename PROPTYPE::reference operator[] (const HandleType &handle) {
            return mesh_->property(prop_, handle);
        }

        /**
         * Enables convenient access to the encapsulated property.
         *
         * For a usage example see this class' documentation.
         *
         * @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
         */
        template<typename HandleType>
        inline typename PROPTYPE::const_reference operator[] (const HandleType &handle) const {
            return mesh_->property(prop_, handle);
        }

        /**
         * Conveniently set the property for an entire range of values.
         *
         * Examples:
         * \code
         * MeshT mesh;
         * PropertyManager<VPropHandleT<double>, MeshT> distance(
         *     mesh, "distance.plugin-example.i8.informatik.rwth-aachen.de");
         * distance.set_range(
         *     mesh.vertices_begin(), mesh.vertices_end(),
         *     std::numeric_limits<double>::infinity());
         * \endcode
         * or
         * \code
         * MeshT::VertexHandle vh;
         * distance.set_range(
         *     mesh.vv_begin(vh), mesh.vv_end(vh),
         *     std::numeric_limits<double>::infinity());
         * \endcode
         *
         * @param begin Start iterator. Needs to dereference to HandleType.
         * @param end End iterator. (Exclusive.)
         * @param value The value the range will be set to.
         */
        template<typename HandleTypeIterator, typename PROP_VALUE>
        void set_range(HandleTypeIterator begin, HandleTypeIterator end,
                const PROP_VALUE &value) {
            for (; begin != end; ++begin)
                (*this)[*begin] = value;
        }

        /**
         * Conveniently transfer the values managed by one property manager
         * onto the values managed by a different property manager.
         *
         * @param begin Start iterator. Needs to dereference to HandleType. Will
         * be used with this property manager.
         * @param end End iterator. (Exclusive.) Will be used with this property
         * manager.
         * @param dst_propmanager The destination property manager.
         * @param dst_begin Start iterator. Needs to dereference to the
         * HandleType of dst_propmanager. Will be used with dst_propmanager.
         * @param dst_end End iterator. (Exclusive.)
         * Will be used with dst_propmanager. Used to double check the bounds.
         */
        template<typename HandleTypeIterator, typename PROPTYPE_2,
                 typename MeshT_2, typename HandleTypeIterator_2>
        void copy_to(HandleTypeIterator begin, HandleTypeIterator end,
                PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
                HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const {

            for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) {
                dst_propmanager[*dst_begin] = (*this)[*begin];
            }
        }

        template<typename RangeType, typename PROPTYPE_2,
                 typename MeshT_2, typename RangeType_2>
        void copy_to(const RangeType &range,
                PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
                const RangeType_2 &dst_range) const {
            copy_to(range.begin(), range.end(), dst_propmanager,
                    dst_range.begin(), dst_range.end());
        }

        /**
         * Copy the values of a property from a source range to
         * a target range. The source range must not be smaller than the
         * target range.
         *
         * @param prop_name Name of the property to copy. Must exist on the
         * source mesh. Will be created on the target mesh if it doesn't exist.
         *
         * @param src_mesh Source mesh from which to copy.
         * @param src_range Source range which to copy. Must not be smaller than
         * dst_range.
         * @param dst_mesh Destination mesh on which to copy.
         * @param dst_range Destination range.
         */
        template<typename RangeType, typename MeshT_2, typename RangeType_2>
        static void copy(const char *prop_name,
                MeshT &src_mesh, const RangeType &src_range,
                MeshT_2 &dst_mesh, const RangeType_2 &dst_range) {

            typedef OpenMesh::PropertyManager<PROPTYPE, MeshT> DstPM;
            DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));

            typedef OpenMesh::PropertyManager<PROPTYPE, MeshT_2> SrcPM;
            SrcPM src(src_mesh, prop_name, true);

            src.copy_to(src_range, dst, dst_range);
        }

    private:
        void deleteProperty() {
            if (!retain_)
                mesh_->remove_property(prop_);
        }

    private:
        MeshT *mesh_;
        PROPTYPE prop_;
        bool retain_;
        std::string name_;
};

} /* namespace OpenMesh */
#endif /* PROPERTYMANAGER_HH_ */
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: testhelper.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: dbo $ $Date: 2002-06-14 13:20:20 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#include <stdio.h>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>

#include <cppuhelper/component_context.hxx>
#include <cppuhelper/servicefactory.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/registry/XSimpleRegistry.hpp>
#include <com/sun/star/registry/XImplementationRegistration.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XComponent.hpp>

#include "testhelper.hxx"

using namespace rtl;
using namespace cppu;
using namespace com::sun::star::uno;
using namespace com::sun::star;
using namespace com::sun::star::lang;
using namespace com::sun::star::registry;

#if (defined UNX) || (defined OS2)
int main( int argc, char * argv[] )
#else
int __cdecl main( int argc, char * argv[] )
#endif
{
    Reference< XMultiComponentFactory > xMgr( createRegistryServiceFactory(
        OUString( RTL_CONSTASCII_USTRINGPARAM("cpputest.rdb") ) ), UNO_QUERY );
    Reference< XComponentContext > xInitialContext;
    OSL_VERIFY( Reference< beans::XPropertySet >( xMgr, UNO_QUERY )->getPropertyValue(
        OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xInitialContext );

    ContextEntry_Init aEntry;
    aEntry.bLateInitService = false;
    aEntry.name = OUString( RTL_CONSTASCII_USTRINGPARAM("bla, bla") );
    aEntry.value = makeAny( (sal_Int32)5 );
    Reference< XComponentContext > xContext( createComponentContext( &aEntry, 1, xInitialContext ) );
    OSL_ASSERT( xContext->getServiceManager() != xMgr ); // must be wrapped one
    OSL_ASSERT(
        Reference< beans::XPropertySet >(
            xContext->getServiceManager(), UNO_QUERY )->getPropertyValue(
                OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) != xInitialContext );

    sal_Bool bSucc = sal_False;
    try
    {
        Reference< XImplementationRegistration > xImplReg(
            xMgr->createInstanceWithContext(
                OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.ImplementationRegistration") ),
                xContext ),
            UNO_QUERY );
        OSL_ENSURE( xImplReg.is(), "### no impl reg!" );

#ifdef UNX
#define REG_PREFIX      "lib"
#ifdef MACOSX
#define DLL_POSTFIX     ".dylib.framework"
#else
#define DLL_POSTFIX     ".so"
#endif
#else
#define REG_PREFIX      ""
#define DLL_POSTFIX     ".dll"
#endif
        OString aLibName( REG_PREFIX );
        aLibName += "corefl";
#ifndef OS2
        aLibName += DLL_POSTFIX;
#endif
        xImplReg->registerImplementation(
            OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.loader.SharedLibrary") ),
            OUString::createFromAscii( aLibName.getStr() ),
            Reference< XSimpleRegistry >() );

        Reference< XMultiServiceFactory > x( xMgr, UNO_QUERY );
        test_ImplHelper( x );
        testPropertyTypeHelper();
        testidlclass( x );
         test_PropertySetHelper();
        test_interfacecontainer();
    }
    catch (Exception & rExc)
    {
        OSL_ENSURE( sal_False, "### exception occured!" );
        OString aMsg( OUStringToOString( rExc.Message, RTL_TEXTENCODING_ASCII_US ) );
        OSL_TRACE( "### exception occured: " );
        OSL_TRACE( aMsg.getStr() );
        OSL_TRACE( "\n" );
    }

    OSL_VERIFY( xContext->getValueByName(
                    OUString( RTL_CONSTASCII_USTRINGPARAM("bla, bla") ) ) == (sal_Int32)5 );
    OSL_VERIFY( ! xInitialContext->getValueByName(
                    OUString( RTL_CONSTASCII_USTRINGPARAM("bla, bla") ) ).hasValue() );
    Reference< XComponent >( xInitialContext, UNO_QUERY )->dispose();
    xMgr.clear();
    xContext.clear();
    xInitialContext.clear();

    printf( "Test finished\n" );
    return 0;
}
<commit_msg>#101685#,#i6886#: merge OOO_STABLE_1_PORTS (1.5-1.5.10.1) -> HEAD<commit_after>/*************************************************************************
 *
 *  $RCSfile: testhelper.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2002-08-15 13:13:13 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#include <stdio.h>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>

#include <cppuhelper/component_context.hxx>
#include <cppuhelper/servicefactory.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/registry/XSimpleRegistry.hpp>
#include <com/sun/star/registry/XImplementationRegistration.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XComponent.hpp>

#include "testhelper.hxx"

using namespace rtl;
using namespace cppu;
using namespace com::sun::star::uno;
using namespace com::sun::star;
using namespace com::sun::star::lang;
using namespace com::sun::star::registry;

#if (defined UNX) || (defined OS2)
int main( int argc, char * argv[] )
#else
int __cdecl main( int argc, char * argv[] )
#endif
{
    Reference< XMultiComponentFactory > xMgr( createRegistryServiceFactory(
        OUString( RTL_CONSTASCII_USTRINGPARAM("cpputest.rdb") ) ), UNO_QUERY );
    Reference< XComponentContext > xInitialContext;
    OSL_VERIFY( Reference< beans::XPropertySet >( xMgr, UNO_QUERY )->getPropertyValue(
        OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xInitialContext );

    ContextEntry_Init aEntry;
    aEntry.bLateInitService = false;
    aEntry.name = OUString( RTL_CONSTASCII_USTRINGPARAM("bla, bla") );
    aEntry.value = makeAny( (sal_Int32)5 );
    Reference< XComponentContext > xContext( createComponentContext( &aEntry, 1, xInitialContext ) );
    OSL_ASSERT( xContext->getServiceManager() != xMgr ); // must be wrapped one
    OSL_ASSERT(
        Reference< beans::XPropertySet >(
            xContext->getServiceManager(), UNO_QUERY )->getPropertyValue(
                OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) != xInitialContext );

    sal_Bool bSucc = sal_False;
    try
    {
        Reference< XImplementationRegistration > xImplReg(
            xMgr->createInstanceWithContext(
                OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.ImplementationRegistration") ),
                xContext ),
            UNO_QUERY );
        OSL_ENSURE( xImplReg.is(), "### no impl reg!" );

#ifdef UNX
#define REG_PREFIX      "lib"
#ifdef MACOSX
#define DLL_POSTFIX     ".dylib"
#else
#define DLL_POSTFIX     ".so"
#endif
#else
#define REG_PREFIX      ""
#define DLL_POSTFIX     ".dll"
#endif
        OString aLibName( REG_PREFIX );
        aLibName += "corefl";
#ifndef OS2
        aLibName += DLL_POSTFIX;
#endif
        xImplReg->registerImplementation(
            OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.loader.SharedLibrary") ),
            OUString::createFromAscii( aLibName.getStr() ),
            Reference< XSimpleRegistry >() );

        Reference< XMultiServiceFactory > x( xMgr, UNO_QUERY );
        test_ImplHelper( x );
        testPropertyTypeHelper();
        testidlclass( x );
         test_PropertySetHelper();
        test_interfacecontainer();
    }
    catch (Exception & rExc)
    {
        OSL_ENSURE( sal_False, "### exception occured!" );
        OString aMsg( OUStringToOString( rExc.Message, RTL_TEXTENCODING_ASCII_US ) );
        OSL_TRACE( "### exception occured: " );
        OSL_TRACE( aMsg.getStr() );
        OSL_TRACE( "\n" );
    }

    OSL_VERIFY( xContext->getValueByName(
                    OUString( RTL_CONSTASCII_USTRINGPARAM("bla, bla") ) ) == (sal_Int32)5 );
    OSL_VERIFY( ! xInitialContext->getValueByName(
                    OUString( RTL_CONSTASCII_USTRINGPARAM("bla, bla") ) ).hasValue() );
    Reference< XComponent >( xInitialContext, UNO_QUERY )->dispose();
    xMgr.clear();
    xContext.clear();
    xInitialContext.clear();

    printf( "Test finished\n" );
    return 0;
}
<|endoftext|>


<commit_before>/**
 * \file
 */

#include <gtest/gtest.h>

#include <sys/stat.h>
#include <fstream>
#include <map>
#include <random>
#include <set>

#include <boost/algorithm/hex.hpp>
#include <boost/archive/iterators/dataflow_exception.hpp>
#include <boost/random/uniform_smallint.hpp>

#include "utilities/utils.h"

bool CharOk(char c) {
  if (('a' <= c) && (c <= 'z')) {
    return true;
  } else if (('0' <= c) && (c <= '9')) {
    return true;
  } else if (c == '-') {
    return true;
  } else {
    return false;
  }
}

bool PrettyNameOk(const std::string &name) {
  if (name.size() < 5) {
    return false;
  }
  for (std::string::const_iterator c = name.begin(); c != name.end(); ++c) {
    if (!CharOk(*c)) {
      return false;
    }
  }
  return true;
}

TEST(Utils, PrettyNameOk) {
  EXPECT_TRUE(PrettyNameOk("foo-bar-123"));
  EXPECT_FALSE(PrettyNameOk("NoCapitals"));
  EXPECT_FALSE(PrettyNameOk(""));
  EXPECT_FALSE(PrettyNameOk("foo-bar-123&"));
}

TEST(Utils, getNetworkInfo) {
  Json::Value netinfo = Utils::getNetworkInfo();

  EXPECT_NE(netinfo["local_ipv4"].asString(), "");
  EXPECT_NE(netinfo["mac"].asString(), "");
  EXPECT_NE(netinfo["hostname"].asString(), "");
}

TEST(Utils, getHostname) { EXPECT_NE(Utils::getHostname(), ""); }

/**
 * Check that aktualizr can generate a pet name.
 *
 * Try 100 times and check that no duplicate names are produced. Tolerate 1
 * duplicate, since we have actually seen it before and it is statistically
 * not unreasonable with our current inputs.
 */
TEST(Utils, GenPrettyNameSane) {
  RecordProperty("zephyr_key", "OTA-986,TST-144");
  std::set<std::string> names;
  for (int i = 0; i < 100; i++) {
    const std::string name = Utils::genPrettyName();
    names.insert(name);
    const auto count = names.count(name);
    if (count > 2) {
      FAIL() << "Something wrong with randomness: " << name;
    } else if (count == 2) {
      std::cerr << "Lucky draw: " << name;
    }
  }
}

TEST(Utils, RandomUuidSane) {
  std::set<std::string> uuids;
  for (int i = 0; i < 1000; i++) {
    std::string uuid = Utils::randomUuid();
    EXPECT_EQ(0, uuids.count(uuid));
    uuids.insert(uuid);
    EXPECT_EQ(1, uuids.count(uuid));
  }
}

TEST(Utils, ToBase64) {
  // Generated using python's base64.b64encode
  EXPECT_EQ("aGVsbG8=", Utils::toBase64("hello"));
  EXPECT_EQ("", Utils::toBase64(""));
  EXPECT_EQ("CQ==", Utils::toBase64("\t"));
  EXPECT_EQ("YWI=", Utils::toBase64("ab"));
  EXPECT_EQ("YWJj", Utils::toBase64("abc"));
}

TEST(Utils, FromBase64) {
  EXPECT_EQ(Utils::fromBase64("aGVsbG8="), "hello");
  EXPECT_EQ(Utils::fromBase64(""), "");
  EXPECT_EQ(Utils::fromBase64("YWI="), "ab");
  EXPECT_EQ(Utils::fromBase64("YWJj"), "abc");
}

TEST(Utils, FromBase64Wrong) {
  EXPECT_THROW(Utils::fromBase64("Привіт"), boost::archive::iterators::dataflow_exception);
  EXPECT_THROW(Utils::fromBase64("aGVsbG8=="), boost::archive::iterators::dataflow_exception);
  EXPECT_THROW(Utils::fromBase64("CQ==="), boost::archive::iterators::dataflow_exception);
}

TEST(Utils, Base64RoundTrip) {
  std::mt19937 gen;
  boost::random::uniform_smallint<char> chars(std::numeric_limits<char>::min(), std::numeric_limits<char>::max());

  boost::random::uniform_smallint<int> length(0, 20);

  for (int test = 0; test < 100; test++) {
    int len = length(gen);
    std::string original;
    for (int i = 0; i < len; i++) {
      original += chars(gen);
    }
    std::string b64 = Utils::toBase64(original);
    std::string output = Utils::fromBase64(b64);
    EXPECT_EQ(original, output);
  }
}

TEST(Utils, ArchiveRead) {
  const std::string archive_path = "tests/test_data/credentials.zip";

  {
    std::ifstream as(archive_path, std::ios::binary | std::ios::in);
    EXPECT_FALSE(as.fail());
    EXPECT_THROW(Utils::readFileFromArchive(as, "bogus_filename"), std::runtime_error);
  }

  {
    std::ifstream as(archive_path, std::ios::binary | std::ios::in);
    EXPECT_FALSE(as.fail());

    std::string url = Utils::readFileFromArchive(as, "autoprov.url");
    EXPECT_EQ(url.rfind("https://", 0), 0);
  }
}

TEST(Utils, ArchiveWrite) {
  std::string archive_bytes;
  {
    std::map<std::string, std::string> fm{{"test", "A"}};
    std::stringstream as;
    Utils::writeArchive(fm, as);
    archive_bytes = as.str();
  }

  {
    std::stringstream as(archive_bytes);
    EXPECT_EQ(Utils::readFileFromArchive(as, "test"), "A");
  }
}

TEST(Utils, TemporaryDirectory) {
  boost::filesystem::path p;
  {
    TemporaryDirectory f("ahint");
    p = f.Path();
    EXPECT_TRUE(boost::filesystem::exists(p));               // The dir should exist
    EXPECT_NE(p.string().find("ahint"), std::string::npos);  // The hint is included in the filename

    struct stat statbuf;
    stat(p.parent_path().c_str(), &statbuf);
    EXPECT_EQ(statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO), S_IRWXU);
  }
  EXPECT_FALSE(boost::filesystem::exists(p));
}

TEST(Utils, TemporaryFile) {
  boost::filesystem::path p;
  {
    TemporaryFile f("ahint");
    p = f.Path();
    EXPECT_FALSE(boost::filesystem::exists(p));  // The file shouldn't already exist
    std::ofstream file(p.c_str());
    file << "test";
    file.close();
    EXPECT_TRUE(file);                                       // The write succeeded
    EXPECT_TRUE(boost::filesystem::exists(p));               // The file should exist here
    EXPECT_NE(p.string().find("ahint"), std::string::npos);  // The hint is included in the filename

    struct stat statbuf;
    stat(p.parent_path().c_str(), &statbuf);
    EXPECT_EQ(statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO), S_IRWXU);
  }
  EXPECT_FALSE(boost::filesystem::exists(p));  // The file gets deleted by the RAII dtor
}

TEST(Utils, TemporaryFilePutContents) {
  TemporaryFile f("ahint");
  f.PutContents("thecontents");
  EXPECT_TRUE(boost::filesystem::exists(f.Path()));
  std::ifstream a(f.Path().c_str());
  std::string b;
  a >> b;
  EXPECT_EQ(b, "thecontents");
}

TEST(Utils, copyDir) {
  TemporaryDirectory temp_dir;

  Utils::writeFile(temp_dir.Path() / "from/1/foo", std::string("foo"));
  Utils::writeFile(temp_dir.Path() / "from/1/2/bar", std::string("bar"));
  Utils::writeFile(temp_dir.Path() / "from/1/2/baz", std::string("baz"));

  Utils::copyDir(temp_dir.Path() / "from", temp_dir.Path() / "to");
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to"));
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to/1"));
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to/1/foo"));
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to/1/2"));
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to/1/2/bar"));
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to/1/2/baz"));
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "to/1/foo"), "foo");
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "to/1/2/bar"), "bar");
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "to/1/2/baz"), "baz");
}

TEST(Utils, writeFileWithoutDirAutoCreation) {
  TemporaryDirectory temp_dir;

  boost::filesystem::create_directories(temp_dir.Path() / "1/2");
  Utils::writeFile(temp_dir.Path() / "1/foo", std::string("foo"), false);
  Utils::writeFile(temp_dir.Path() / "1/2/bar", std::string("bar"), false);

  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/foo"), "foo");
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/2/bar"), "bar");
}

TEST(Utils, writeFileWithDirAutoCreation) {
  TemporaryDirectory temp_dir;

  Utils::writeFile(temp_dir.Path() / "1/foo", std::string("foo"), true);
  Utils::writeFile(temp_dir.Path() / "1/2/bar", std::string("bar"), true);

  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/foo"), "foo");
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/2/bar"), "bar");
}

TEST(Utils, writeFileWithDirAutoCreationDefault) {
  TemporaryDirectory temp_dir;

  Utils::writeFile(temp_dir.Path() / "1/foo", std::string("foo"));
  Utils::writeFile(temp_dir.Path() / "1/2/bar", std::string("bar"));

  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/foo"), "foo");
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/2/bar"), "bar");
}

TEST(Utils, writeFileWithoutDirAutoCreationException) {
  TemporaryDirectory temp_dir;

  try {
    Utils::writeFile(temp_dir.Path() / "1/foo", std::string("foo"), false);
    EXPECT_TRUE(false);
  } catch (...) {
  }
}

TEST(Utils, writeFileJson) {
  TemporaryDirectory temp_dir;

  Json::Value val;
  val["key"] = "val";

  Utils::writeFile(temp_dir.Path() / "1/foo", val);
  Json::Value result_json = Utils::parseJSONFile(temp_dir.Path() / "1/foo");
  EXPECT_EQ(result_json["key"].asString(), val["key"].asString());
}

TEST(Utils, ipUtils) {
  int fd = socket(AF_INET6, SOCK_STREAM, 0);

  EXPECT_NE(fd, -1);
  SocketHandle hdl(new int(fd));

  sockaddr_in6 sa;

  memset(&sa, 0, sizeof(sa));
  sa.sin6_family = AF_INET6;
  sa.sin6_port = htons(0);
  sa.sin6_addr = IN6ADDR_ANY_INIT;

  int reuseaddr = 1;
  if (setsockopt(*hdl, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) < 0) {
    throw std::runtime_error("setsockopt(SO_REUSEADDR) failed");
  }

  EXPECT_NE(bind(*hdl, reinterpret_cast<const sockaddr *>(&sa), sizeof(sa)), -1);

  sockaddr_storage ss;
  EXPECT_NO_THROW(ss = Utils::ipGetSockaddr(*hdl));

  EXPECT_NE(Utils::ipDisplayName(ss), "unknown");
  EXPECT_NE(Utils::ipPort(ss), -1);
}

TEST(Utils, shell) {
  std::string out;
  int statuscode = Utils::shell("ls /", &out);
  EXPECT_EQ(statuscode, 0);

  statuscode = Utils::shell("ls /nonexistentdir123", &out);
  EXPECT_NE(statuscode, 0);
}

TEST(Utils, urlencode) { EXPECT_EQ(Utils::urlEncode("test! test@ test#"), "test%21%20test%40%20test%23"); }

TEST(Utils, BasedPath) {
  BasedPath bp("a/test.xml");

  EXPECT_EQ(BasedPath(bp.get("")), bp);
  EXPECT_EQ(bp.get("/"), "/a/test.xml");
  EXPECT_EQ(bp.get("/x"), "/x/a/test.xml");

  BasedPath abp("/a/test.xml");

  EXPECT_EQ(abp.get(""), "/a/test.xml");
  EXPECT_EQ(abp.get("/root/var"), "/a/test.xml");
}

TEST(Utils, TrimNewline) {
  TemporaryFile f("newline");
  std::string input = "test with newline";
  Utils::writeFile(f.Path(), input + "\n");
  std::string output = Utils::readFile(f.Path(), false);
  EXPECT_EQ(output, input + "\n");
  output = Utils::readFile(f.Path(), true);
  EXPECT_EQ(output, input);
}

#ifndef __NO_MAIN__
int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
#endif
<commit_msg>Add basic getHardwareInfo test.<commit_after>/**
 * \file
 */

#include <gtest/gtest.h>

#include <sys/stat.h>
#include <fstream>
#include <map>
#include <random>
#include <set>

#include <boost/algorithm/hex.hpp>
#include <boost/archive/iterators/dataflow_exception.hpp>
#include <boost/random/uniform_smallint.hpp>

#include "utilities/utils.h"

bool CharOk(char c) {
  if (('a' <= c) && (c <= 'z')) {
    return true;
  } else if (('0' <= c) && (c <= '9')) {
    return true;
  } else if (c == '-') {
    return true;
  } else {
    return false;
  }
}

bool PrettyNameOk(const std::string &name) {
  if (name.size() < 5) {
    return false;
  }
  for (std::string::const_iterator c = name.begin(); c != name.end(); ++c) {
    if (!CharOk(*c)) {
      return false;
    }
  }
  return true;
}

TEST(Utils, PrettyNameOk) {
  EXPECT_TRUE(PrettyNameOk("foo-bar-123"));
  EXPECT_FALSE(PrettyNameOk("NoCapitals"));
  EXPECT_FALSE(PrettyNameOk(""));
  EXPECT_FALSE(PrettyNameOk("foo-bar-123&"));
}

/* Read hardware info from the system. */
TEST(Utils, getHardwareInfo) {
  Json::Value hwinfo = Utils::getHardwareInfo();
  EXPECT_NE(hwinfo, Json::Value());
  EXPECT_FALSE(hwinfo.isArray());
}

TEST(Utils, getNetworkInfo) {
  Json::Value netinfo = Utils::getNetworkInfo();

  EXPECT_NE(netinfo["local_ipv4"].asString(), "");
  EXPECT_NE(netinfo["mac"].asString(), "");
  EXPECT_NE(netinfo["hostname"].asString(), "");
}

TEST(Utils, getHostname) { EXPECT_NE(Utils::getHostname(), ""); }

/**
 * Check that aktualizr can generate a pet name.
 *
 * Try 100 times and check that no duplicate names are produced. Tolerate 1
 * duplicate, since we have actually seen it before and it is statistically
 * not unreasonable with our current inputs.
 */
TEST(Utils, GenPrettyNameSane) {
  RecordProperty("zephyr_key", "OTA-986,TST-144");
  std::set<std::string> names;
  for (int i = 0; i < 100; i++) {
    const std::string name = Utils::genPrettyName();
    names.insert(name);
    const auto count = names.count(name);
    if (count > 2) {
      FAIL() << "Something wrong with randomness: " << name;
    } else if (count == 2) {
      std::cerr << "Lucky draw: " << name;
    }
  }
}

TEST(Utils, RandomUuidSane) {
  std::set<std::string> uuids;
  for (int i = 0; i < 1000; i++) {
    std::string uuid = Utils::randomUuid();
    EXPECT_EQ(0, uuids.count(uuid));
    uuids.insert(uuid);
    EXPECT_EQ(1, uuids.count(uuid));
  }
}

TEST(Utils, ToBase64) {
  // Generated using python's base64.b64encode
  EXPECT_EQ("aGVsbG8=", Utils::toBase64("hello"));
  EXPECT_EQ("", Utils::toBase64(""));
  EXPECT_EQ("CQ==", Utils::toBase64("\t"));
  EXPECT_EQ("YWI=", Utils::toBase64("ab"));
  EXPECT_EQ("YWJj", Utils::toBase64("abc"));
}

TEST(Utils, FromBase64) {
  EXPECT_EQ(Utils::fromBase64("aGVsbG8="), "hello");
  EXPECT_EQ(Utils::fromBase64(""), "");
  EXPECT_EQ(Utils::fromBase64("YWI="), "ab");
  EXPECT_EQ(Utils::fromBase64("YWJj"), "abc");
}

TEST(Utils, FromBase64Wrong) {
  EXPECT_THROW(Utils::fromBase64("Привіт"), boost::archive::iterators::dataflow_exception);
  EXPECT_THROW(Utils::fromBase64("aGVsbG8=="), boost::archive::iterators::dataflow_exception);
  EXPECT_THROW(Utils::fromBase64("CQ==="), boost::archive::iterators::dataflow_exception);
}

TEST(Utils, Base64RoundTrip) {
  std::mt19937 gen;
  boost::random::uniform_smallint<char> chars(std::numeric_limits<char>::min(), std::numeric_limits<char>::max());

  boost::random::uniform_smallint<int> length(0, 20);

  for (int test = 0; test < 100; test++) {
    int len = length(gen);
    std::string original;
    for (int i = 0; i < len; i++) {
      original += chars(gen);
    }
    std::string b64 = Utils::toBase64(original);
    std::string output = Utils::fromBase64(b64);
    EXPECT_EQ(original, output);
  }
}

TEST(Utils, ArchiveRead) {
  const std::string archive_path = "tests/test_data/credentials.zip";

  {
    std::ifstream as(archive_path, std::ios::binary | std::ios::in);
    EXPECT_FALSE(as.fail());
    EXPECT_THROW(Utils::readFileFromArchive(as, "bogus_filename"), std::runtime_error);
  }

  {
    std::ifstream as(archive_path, std::ios::binary | std::ios::in);
    EXPECT_FALSE(as.fail());

    std::string url = Utils::readFileFromArchive(as, "autoprov.url");
    EXPECT_EQ(url.rfind("https://", 0), 0);
  }
}

TEST(Utils, ArchiveWrite) {
  std::string archive_bytes;
  {
    std::map<std::string, std::string> fm{{"test", "A"}};
    std::stringstream as;
    Utils::writeArchive(fm, as);
    archive_bytes = as.str();
  }

  {
    std::stringstream as(archive_bytes);
    EXPECT_EQ(Utils::readFileFromArchive(as, "test"), "A");
  }
}

TEST(Utils, TemporaryDirectory) {
  boost::filesystem::path p;
  {
    TemporaryDirectory f("ahint");
    p = f.Path();
    EXPECT_TRUE(boost::filesystem::exists(p));               // The dir should exist
    EXPECT_NE(p.string().find("ahint"), std::string::npos);  // The hint is included in the filename

    struct stat statbuf;
    stat(p.parent_path().c_str(), &statbuf);
    EXPECT_EQ(statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO), S_IRWXU);
  }
  EXPECT_FALSE(boost::filesystem::exists(p));
}

TEST(Utils, TemporaryFile) {
  boost::filesystem::path p;
  {
    TemporaryFile f("ahint");
    p = f.Path();
    EXPECT_FALSE(boost::filesystem::exists(p));  // The file shouldn't already exist
    std::ofstream file(p.c_str());
    file << "test";
    file.close();
    EXPECT_TRUE(file);                                       // The write succeeded
    EXPECT_TRUE(boost::filesystem::exists(p));               // The file should exist here
    EXPECT_NE(p.string().find("ahint"), std::string::npos);  // The hint is included in the filename

    struct stat statbuf;
    stat(p.parent_path().c_str(), &statbuf);
    EXPECT_EQ(statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO), S_IRWXU);
  }
  EXPECT_FALSE(boost::filesystem::exists(p));  // The file gets deleted by the RAII dtor
}

TEST(Utils, TemporaryFilePutContents) {
  TemporaryFile f("ahint");
  f.PutContents("thecontents");
  EXPECT_TRUE(boost::filesystem::exists(f.Path()));
  std::ifstream a(f.Path().c_str());
  std::string b;
  a >> b;
  EXPECT_EQ(b, "thecontents");
}

TEST(Utils, copyDir) {
  TemporaryDirectory temp_dir;

  Utils::writeFile(temp_dir.Path() / "from/1/foo", std::string("foo"));
  Utils::writeFile(temp_dir.Path() / "from/1/2/bar", std::string("bar"));
  Utils::writeFile(temp_dir.Path() / "from/1/2/baz", std::string("baz"));

  Utils::copyDir(temp_dir.Path() / "from", temp_dir.Path() / "to");
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to"));
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to/1"));
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to/1/foo"));
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to/1/2"));
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to/1/2/bar"));
  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "to/1/2/baz"));
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "to/1/foo"), "foo");
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "to/1/2/bar"), "bar");
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "to/1/2/baz"), "baz");
}

TEST(Utils, writeFileWithoutDirAutoCreation) {
  TemporaryDirectory temp_dir;

  boost::filesystem::create_directories(temp_dir.Path() / "1/2");
  Utils::writeFile(temp_dir.Path() / "1/foo", std::string("foo"), false);
  Utils::writeFile(temp_dir.Path() / "1/2/bar", std::string("bar"), false);

  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/foo"), "foo");
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/2/bar"), "bar");
}

TEST(Utils, writeFileWithDirAutoCreation) {
  TemporaryDirectory temp_dir;

  Utils::writeFile(temp_dir.Path() / "1/foo", std::string("foo"), true);
  Utils::writeFile(temp_dir.Path() / "1/2/bar", std::string("bar"), true);

  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/foo"), "foo");
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/2/bar"), "bar");
}

TEST(Utils, writeFileWithDirAutoCreationDefault) {
  TemporaryDirectory temp_dir;

  Utils::writeFile(temp_dir.Path() / "1/foo", std::string("foo"));
  Utils::writeFile(temp_dir.Path() / "1/2/bar", std::string("bar"));

  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/foo"), "foo");
  EXPECT_EQ(Utils::readFile(temp_dir.Path() / "1/2/bar"), "bar");
}

TEST(Utils, writeFileWithoutDirAutoCreationException) {
  TemporaryDirectory temp_dir;

  try {
    Utils::writeFile(temp_dir.Path() / "1/foo", std::string("foo"), false);
    EXPECT_TRUE(false);
  } catch (...) {
  }
}

TEST(Utils, writeFileJson) {
  TemporaryDirectory temp_dir;

  Json::Value val;
  val["key"] = "val";

  Utils::writeFile(temp_dir.Path() / "1/foo", val);
  Json::Value result_json = Utils::parseJSONFile(temp_dir.Path() / "1/foo");
  EXPECT_EQ(result_json["key"].asString(), val["key"].asString());
}

TEST(Utils, ipUtils) {
  int fd = socket(AF_INET6, SOCK_STREAM, 0);

  EXPECT_NE(fd, -1);
  SocketHandle hdl(new int(fd));

  sockaddr_in6 sa;

  memset(&sa, 0, sizeof(sa));
  sa.sin6_family = AF_INET6;
  sa.sin6_port = htons(0);
  sa.sin6_addr = IN6ADDR_ANY_INIT;

  int reuseaddr = 1;
  if (setsockopt(*hdl, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) < 0) {
    throw std::runtime_error("setsockopt(SO_REUSEADDR) failed");
  }

  EXPECT_NE(bind(*hdl, reinterpret_cast<const sockaddr *>(&sa), sizeof(sa)), -1);

  sockaddr_storage ss;
  EXPECT_NO_THROW(ss = Utils::ipGetSockaddr(*hdl));

  EXPECT_NE(Utils::ipDisplayName(ss), "unknown");
  EXPECT_NE(Utils::ipPort(ss), -1);
}

TEST(Utils, shell) {
  std::string out;
  int statuscode = Utils::shell("ls /", &out);
  EXPECT_EQ(statuscode, 0);

  statuscode = Utils::shell("ls /nonexistentdir123", &out);
  EXPECT_NE(statuscode, 0);
}

TEST(Utils, urlencode) { EXPECT_EQ(Utils::urlEncode("test! test@ test#"), "test%21%20test%40%20test%23"); }

TEST(Utils, BasedPath) {
  BasedPath bp("a/test.xml");

  EXPECT_EQ(BasedPath(bp.get("")), bp);
  EXPECT_EQ(bp.get("/"), "/a/test.xml");
  EXPECT_EQ(bp.get("/x"), "/x/a/test.xml");

  BasedPath abp("/a/test.xml");

  EXPECT_EQ(abp.get(""), "/a/test.xml");
  EXPECT_EQ(abp.get("/root/var"), "/a/test.xml");
}

TEST(Utils, TrimNewline) {
  TemporaryFile f("newline");
  std::string input = "test with newline";
  Utils::writeFile(f.Path(), input + "\n");
  std::string output = Utils::readFile(f.Path(), false);
  EXPECT_EQ(output, input + "\n");
  output = Utils::readFile(f.Path(), true);
  EXPECT_EQ(output, input);
}

#ifndef __NO_MAIN__
int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
#endif
<|endoftext|>


<commit_before>//
// C++ Implementation: PresetFactoryManager
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef __PRESET_FACTORY_MANAGER_HPP
#define __PRESET_FACTORY_MANAGER_HPP
#include "PresetFactory.hpp"

/// A simple exception class to strongly type all preset factory related issues
class PresetFactoryException : public std::exception
{
	public:
		inline PresetFactoryException(const std::string & message) : _message(message) {}
		virtual ~PresetFactoryException() throw() {}
		const std::string & message() const { return _message; }

	private:
		std::string _message;
};

/// A manager of preset factories
class PresetFactoryManager {

	public:
		PresetFactoryManager();
		~PresetFactoryManager();

		/// Initializes the manager with mesh sizes specified
		/// \param gx the width of the mesh
		/// \param gy the height of the mesh
		/// \note This must be called before useful behavior occurs
		void initialize(int gx, int gy);

		/// Requests a factory given a preset extension type
		/// \param extension a string denoting the preset suffix type
		/// \throws a PresetFactoryException if the extension is unhandled
		/// \returns a valid preset factory associated with the extension
		PresetFactory & factory(const std::string & extension);

		/// Tests when an extension has been registered with a factory
		/// \param extension the file name extension to verify
		/// \returns true if a factory exists, false otherwise
		bool extensionHandled(const std::string & extension) const;

	private:
		int _gx, _gy;
		mutable std::map<std::string, PresetFactory *> _factoryMap;
		mutable std::vector<PresetFactory *> _factoryList;
		void registerFactory(const std::string & extension, PresetFactory * factory);

};
#endif
<commit_msg>comment typo fix in factory() method of PresetFactoryManager<commit_after>//
// C++ Implementation: PresetFactoryManager
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef __PRESET_FACTORY_MANAGER_HPP
#define __PRESET_FACTORY_MANAGER_HPP
#include "PresetFactory.hpp"

/// A simple exception class to strongly type all preset factory related issues
class PresetFactoryException : public std::exception
{
	public:
		inline PresetFactoryException(const std::string & message) : _message(message) {}
		virtual ~PresetFactoryException() throw() {}
		const std::string & message() const { return _message; }

	private:
		std::string _message;
};

/// A manager of preset factories
class PresetFactoryManager {

	public:
		PresetFactoryManager();
		~PresetFactoryManager();

		/// Initializes the manager with mesh sizes specified
		/// \param gx the width of the mesh
		/// \param gy the height of the mesh
		/// \note This must be called before useful behavior occurs
		void initialize(int gx, int gy);

		/// Requests a factory given a preset extension type
		/// \param extension a string denoting the preset suffix type
		/// \throws PresetFactoryException if the extension is unhandled
		/// \returns a valid preset factory associated with the extension
		PresetFactory & factory(const std::string & extension);

		/// Tests when an extension has been registered with a factory
		/// \param extension the file name extension to verify
		/// \returns true if a factory exists, false otherwise
		bool extensionHandled(const std::string & extension) const;

	private:
		int _gx, _gy;
		mutable std::map<std::string, PresetFactory *> _factoryMap;
		mutable std::vector<PresetFactory *> _factoryList;
		void registerFactory(const std::string & extension, PresetFactory * factory);

};
#endif
<|endoftext|>


<commit_before>#ifndef __STDAIR_STDAIR_EXCEPTIONS_HPP
#define __STDAIR_STDAIR_EXCEPTIONS_HPP

// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <string>

namespace stdair {

  /**
   * @brief Root of the stdair exceptions.
   *
   * All the stdair exceptions inherit from that root, allowing to
   * catch them and to spot them easily when arising in code wrapping
   * the stdair library.
   */
  class RootException : public std::exception {
  public:
    /**
     * Main Constructor.
     */
    RootException (const std::string& iWhat) : _what (iWhat) {}
    /**
     * Default constructor.
     */
    RootException() : _what ("No further details") {}

    /**
     * Destructor.
     */
    virtual ~RootException() throw() {}

    /**
     * Give the details of the exception.
     */
    const char* what() const throw() {
      return _what.c_str();
    }

  protected:
    /**
     * Details for the exception.
     */
    std::string _what;
  };

  /** File not found. */
  class FileNotFoundException : public RootException {
  public:
    /** Constructor. */
    FileNotFoundException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Non initialised log service. */
  class NonInitialisedLogServiceException : public RootException {
  public:
    /** Constructor. */
    NonInitialisedLogServiceException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Non initialised service. */
  class NonInitialisedServiceException : public RootException {
  public:
    /** Constructor. */
    NonInitialisedServiceException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Non initialised container. */
  class NonInitialisedContainerException : public RootException {
  public:
    /** Constructor. */
    NonInitialisedContainerException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Non initialised relationship. */
  class NonInitialisedRelationShipException : public RootException {
  public:
    /** Constructor. */
    NonInitialisedRelationShipException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Memory allocation. */
  class MemoryAllocationException : public RootException {
  public:
    /** Constructor. */
    MemoryAllocationException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Object link. */
  class ObjectLinkingException : public RootException {
  public:
    /** Constructor. */
    ObjectLinkingException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Document not found. */
  class DocumentNotFoundException : public RootException {
  public:
    /** Constructor. */
    DocumentNotFoundException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Parser. */
  class ParserException : public RootException {
  public:
    /** Constructor. */
    ParserException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Serialisation. */
  class SerialisationException : public RootException {
  public:
    /** Constructor. */
    SerialisationException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Not found key. */
  class KeyNotFoundException : public RootException {
  public:
    /** Constructor. */
    KeyNotFoundException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Code conversion. */
  class CodeConversionException : public ParserException {
  public:
    /** Constructor. */
    CodeConversionException (const std::string& iWhat)
      : ParserException (iWhat) {}
  };

  /** Code duplication. */
  class CodeDuplicationException : public ParserException {
  public:
    /** Constructor. */
    CodeDuplicationException (const std::string& iWhat)
      : ParserException(iWhat) {}
  };

  /** Duplicated object. */
  class ObjectCreationgDuplicationException : public ParserException {
  public:
    /** Constructor. */
    ObjectCreationgDuplicationException (const std::string& iWhat)
      : ParserException (iWhat) {}
  };

  /** Not found object. */
  class ObjectNotFoundException : public RootException {
  public:
    /** Constructor. */
    ObjectNotFoundException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Database. */
  class SQLDatabaseException : public RootException {
  public:
    /** Constructor. */
    SQLDatabaseException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Non initialised database session. */
  class NonInitialisedDBSessionManagerException : public RootException {
  public:
    /** Constructor. */
    NonInitialisedDBSessionManagerException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Database connection. */
  class SQLDatabaseConnectionImpossibleException : public SQLDatabaseException {
  public:
    /** Constructor. */
    SQLDatabaseConnectionImpossibleException (const std::string& iWhat)
      : SQLDatabaseException (iWhat) {}
  };

  /** Event. */
  class EventException : public RootException {
  public:
    /** Constructor. */
    EventException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** EventQueue. */
  class EventQueueException : public RootException {
  public:
    /** Constructor. */
    EventQueueException (const std::string& iWhat) : RootException (iWhat) {}
  };

}
#endif // __STDAIR_STDAIR_EXCEPTIONS_HPP
<commit_msg>[Dev] Added an exception to throw when input file parsing failed.<commit_after>#ifndef __STDAIR_STDAIR_EXCEPTIONS_HPP
#define __STDAIR_STDAIR_EXCEPTIONS_HPP

// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <string>

namespace stdair {

  /**
   * @brief Root of the stdair exceptions.
   *
   * All the stdair exceptions inherit from that root, allowing to
   * catch them and to spot them easily when arising in code wrapping
   * the stdair library.
   */
  class RootException : public std::exception {
  public:
    /**
     * Main Constructor.
     */
    RootException (const std::string& iWhat) : _what (iWhat) {}
    /**
     * Default constructor.
     */
    RootException() : _what ("No further details") {}

    /**
     * Destructor.
     */
    virtual ~RootException() throw() {}

    /**
     * Give the details of the exception.
     */
    const char* what() const throw() {
      return _what.c_str();
    }

  protected:
    /**
     * Details for the exception.
     */
    std::string _what;
  };

  /** File not found. */
  class FileNotFoundException : public RootException {
  public:
    /** Constructor. */
    FileNotFoundException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Non initialised log service. */
  class NonInitialisedLogServiceException : public RootException {
  public:
    /** Constructor. */
    NonInitialisedLogServiceException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Non initialised service. */
  class NonInitialisedServiceException : public RootException {
  public:
    /** Constructor. */
    NonInitialisedServiceException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Non initialised container. */
  class NonInitialisedContainerException : public RootException {
  public:
    /** Constructor. */
    NonInitialisedContainerException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Non initialised relationship. */
  class NonInitialisedRelationShipException : public RootException {
  public:
    /** Constructor. */
    NonInitialisedRelationShipException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Memory allocation. */
  class MemoryAllocationException : public RootException {
  public:
    /** Constructor. */
    MemoryAllocationException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Object link. */
  class ObjectLinkingException : public RootException {
  public:
    /** Constructor. */
    ObjectLinkingException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Document not found. */
  class DocumentNotFoundException : public RootException {
  public:
    /** Constructor. */
    DocumentNotFoundException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Parser. */
  class ParserException : public RootException {
  public:
    /** Constructor. */
    ParserException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Serialisation. */
  class SerialisationException : public RootException {
  public:
    /** Constructor. */
    SerialisationException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Not found key. */
  class KeyNotFoundException : public RootException {
  public:
    /** Constructor. */
    KeyNotFoundException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Code conversion. */
  class CodeConversionException : public ParserException {
  public:
    /** Constructor. */
    CodeConversionException (const std::string& iWhat)
      : ParserException (iWhat) {}
  };

  /** Code duplication. */
  class CodeDuplicationException : public ParserException {
  public:
    /** Constructor. */
    CodeDuplicationException (const std::string& iWhat)
      : ParserException(iWhat) {}
  };

  /** Duplicated object. */
  class ObjectCreationgDuplicationException : public ParserException {
  public:
    /** Constructor. */
    ObjectCreationgDuplicationException (const std::string& iWhat)
      : ParserException (iWhat) {}
  };

  /** Not found object. */
  class ObjectNotFoundException : public RootException {
  public:
    /** Constructor. */
    ObjectNotFoundException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Input file parsing failure. */
  class ParsingFileFailedException : public ParserException {
  public:
    /** Constructor. */
    ParsingFileFailedException (const std::string& iWhat)
      : ParserException (iWhat) {}
  };

  /** Database. */
  class SQLDatabaseException : public RootException {
  public:
    /** Constructor. */
    SQLDatabaseException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** Non initialised database session. */
  class NonInitialisedDBSessionManagerException : public RootException {
  public:
    /** Constructor. */
    NonInitialisedDBSessionManagerException (const std::string& iWhat)
      : RootException (iWhat) {}
  };

  /** Database connection. */
  class SQLDatabaseConnectionImpossibleException : public SQLDatabaseException {
  public:
    /** Constructor. */
    SQLDatabaseConnectionImpossibleException (const std::string& iWhat)
      : SQLDatabaseException (iWhat) {}
  };

  /** Event. */
  class EventException : public RootException {
  public:
    /** Constructor. */
    EventException (const std::string& iWhat) : RootException (iWhat) {}
  };

  /** EventQueue. */
  class EventQueueException : public RootException {
  public:
    /** Constructor. */
    EventQueueException (const std::string& iWhat) : RootException (iWhat) {}
  };

}
#endif // __STDAIR_STDAIR_EXCEPTIONS_HPP
<|endoftext|>