<commit_before>/*
 Copyright (c) 2014, J.D. Koftinoff Software, Ltd.
 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 of J.D. Koftinoff Software, Ltd. 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.
 */
#pragma once

#include "JDKSAvdeccMCU_World.hpp"
#include "JDKSAvdeccMCU_FixedBuffer.hpp"
#include "JDKSAvdeccMCU_Frame.hpp"

namespace JDKSAvdeccMCU
{

///
/// \brief The Ethernet Frame class
///
/// A type of FixedBuffer that adds methods to manage
/// Ethernet Frame headers and payloads and a timestamp
///
class Frame : public FixedBuffer
{
  protected:
    ///
    /// \brief m_time_in_ms The timestamp of the frame in milliseconds
    ///
    jdksavdecc_timestamp_in_milliseconds m_time_in_ms;

  public:
    ///
    /// \brief Frame Constructor of a Frame
    /// \param time_in_ms The time in milliseconds
    /// \param buf The buffer storage area to use
    /// \param len The buffer storage area length
    /// \param dest_mac The destination MAC address
    /// \param src_mac The source MAC Address
    /// \param ethertype The Ethertype
    ///
    Frame( jdksavdecc_timestamp_in_milliseconds time_in_ms,
           uint8_t *buf,
           uint16_t len,
           Eui48 const &dest_mac,
           Eui48 const &src_mac,
           uint16_t ethertype )
        : FixedBuffer( buf, len ), m_time_in_ms( time_in_ms )
    {
        putEUI48( dest_mac );
        putEUI48( src_mac );
        putDoublet( ethertype );
    }

    ///
    /// \brief Frame Constructor of a Frame
    /// \param time_in_ms The time in milliseconds
    /// \param buf The buffer storage area to use
    /// \param len The buffer storage area length
    ///
    Frame( jdksavdecc_timestamp_in_milliseconds time_in_ms,
           uint8_t *buf,
           uint16_t len )
        : FixedBuffer( buf, len ), m_time_in_ms( time_in_ms )
    {
    }

    ///
    /// \brief getDA Get the Frame's Destination Address
    /// \return The Eui48
    ///
    Eui48 getDA() const
    {
        return getEUI48( JDKSAVDECC_FRAME_HEADER_DA_OFFSET );
    }

    ///
    /// \brief setDA Set the Frame's Destination Address
    /// \param da The Eui48
    ///
    void setDA( Eui48 const &da )
    {
        setEUI48( da, JDKSAVDECC_FRAME_HEADER_DA_OFFSET );
    }

    ///
    /// \brief getDA Get the Frame's Source Address
    /// \return The Eui48
    ///
    Eui48 getSA() const
    {
        return getEUI48( JDKSAVDECC_FRAME_HEADER_SA_OFFSET );
    }

    ///
    /// \brief setDA Set the Frame's Source Address
    /// \param sa The Eui48
    ///
    void setSA( Eui48 const &sa )
    {
        setEUI48( sa, JDKSAVDECC_FRAME_HEADER_SA_OFFSET );
    }

    ///
    /// \brief getEtherType Get the Frame's EtherType
    /// Note: does not manage tagged frames
    /// \return The EtherType value
    ///
    uint16_t getEtherType() const
    {
        return getDoublet( JDKSAVDECC_FRAME_HEADER_ETHERTYPE_OFFSET );
    }

    ///
    /// \brief setEtherType Set the Frame's EtherType
    /// Note: does not manage tagged frames
    /// \param et The EtherType value
    ///
    void setEtherType( uint16_t et )
    {
        setDoublet( et, JDKSAVDECC_FRAME_HEADER_ETHERTYPE_OFFSET );
    }

    ///
    /// \brief getPayload Get the Frame's Payload
    /// Note: does not manage tagged frames
    /// \return The raw uint8_t pointer to the payload
    ///
    uint8_t *getPayload() { return &m_buf[JDKSAVDECC_FRAME_HEADER_LEN]; }

    ///
    /// \brief getPayload Get The Frame's const Payload
    /// \return The raw uint8_t const pointer to the payload
    ///
    uint8_t const *getPayload() const
    {
        return &m_buf[JDKSAVDECC_FRAME_HEADER_LEN];
    }

    ///
    /// \brief getTimeInMilliseconds Get the timestamp in milliseconds
    /// \return The timestamp
    ///
    jdksavdecc_timestamp_in_milliseconds getTimeInMilliseconds() const
    {
        return m_time_in_ms;
    }

    ///
    /// \brief setTimeInMilliseconds Set the timestamp in milliseconds
    /// \param v The timestamp
    ///
    void setTimeInMilliseconds( jdksavdecc_timestamp_in_milliseconds v )
    {
        m_time_in_ms = v;
    }
};

///
/// \brief The Ethernet FrameWithSize class
///
/// A subclass of Frame which is templatized on a MaxSize
/// argument and allocates a static buffer of that size
///
template <size_t MaxSize>
class FrameWithSize : public Frame
{
  protected:
    ///
    /// \brief m_buf_storage The storage for the frame
    ///
    uint8_t m_buf_storage[MaxSize];

  public:
    ///
    /// \brief FrameWithSize Constructor of an empty allocated frame
    ///
    FrameWithSize() : Frame( 0, m_buf_storage, MaxSize ) {}

    ///
    /// \brief FrameWithSize Constructor of an empty frame with timestamp
    /// \param time_in_ms The timestamp in milliseconds
    ///
    FrameWithSize( jdksavdecc_timestamp_in_milliseconds time_in_ms )
        : Frame( time_in_ms, m_buf_storage, MaxSize )
    {
    }

    ///
    /// \brief FrameWithSize Constructor of a frame with header and timestamp
    /// \param time_in_ms The timestamp in milliseconds
    /// \param dest_mac The destination MAC adddress
    /// \param src_mac The source MAC address
    /// \param ethertype The EtherType
    ///
    FrameWithSize( jdksavdecc_timestamp_in_milliseconds time_in_ms,
                   Eui48 const &dest_mac,
                   Eui48 const &src_mac,
                   uint16_t ethertype )
        : Frame(
              time_in_ms, m_buf_storage, MaxSize, dest_mac, src_mac, ethertype )
    {
    }
};
}
<commit_msg>Give default size for FrameWithSize to allow full size PDU including header<commit_after>/*
 Copyright (c) 2014, J.D. Koftinoff Software, Ltd.
 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 of J.D. Koftinoff Software, Ltd. 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.
 */
#pragma once

#include "JDKSAvdeccMCU_World.hpp"
#include "JDKSAvdeccMCU_FixedBuffer.hpp"
#include "JDKSAvdeccMCU_Frame.hpp"

namespace JDKSAvdeccMCU
{

///
/// \brief The Ethernet Frame class
///
/// A type of FixedBuffer that adds methods to manage
/// Ethernet Frame headers and payloads and a timestamp
///
class Frame : public FixedBuffer
{
  protected:
    ///
    /// \brief m_time_in_ms The timestamp of the frame in milliseconds
    ///
    jdksavdecc_timestamp_in_milliseconds m_time_in_ms;

  public:
    ///
    /// \brief Frame Constructor of a Frame
    /// \param time_in_ms The time in milliseconds
    /// \param buf The buffer storage area to use
    /// \param len The buffer storage area length
    /// \param dest_mac The destination MAC address
    /// \param src_mac The source MAC Address
    /// \param ethertype The Ethertype
    ///
    Frame( jdksavdecc_timestamp_in_milliseconds time_in_ms,
           uint8_t *buf,
           uint16_t len,
           Eui48 const &dest_mac,
           Eui48 const &src_mac,
           uint16_t ethertype )
        : FixedBuffer( buf, len ), m_time_in_ms( time_in_ms )
    {
        putEUI48( dest_mac );
        putEUI48( src_mac );
        putDoublet( ethertype );
    }

    ///
    /// \brief Frame Constructor of a Frame
    /// \param time_in_ms The time in milliseconds
    /// \param buf The buffer storage area to use
    /// \param len The buffer storage area length
    ///
    Frame( jdksavdecc_timestamp_in_milliseconds time_in_ms,
           uint8_t *buf,
           uint16_t len )
        : FixedBuffer( buf, len ), m_time_in_ms( time_in_ms )
    {
    }

    ///
    /// \brief getDA Get the Frame's Destination Address
    /// \return The Eui48
    ///
    Eui48 getDA() const
    {
        return getEUI48( JDKSAVDECC_FRAME_HEADER_DA_OFFSET );
    }

    ///
    /// \brief setDA Set the Frame's Destination Address
    /// \param da The Eui48
    ///
    void setDA( Eui48 const &da )
    {
        setEUI48( da, JDKSAVDECC_FRAME_HEADER_DA_OFFSET );
    }

    ///
    /// \brief getDA Get the Frame's Source Address
    /// \return The Eui48
    ///
    Eui48 getSA() const
    {
        return getEUI48( JDKSAVDECC_FRAME_HEADER_SA_OFFSET );
    }

    ///
    /// \brief setDA Set the Frame's Source Address
    /// \param sa The Eui48
    ///
    void setSA( Eui48 const &sa )
    {
        setEUI48( sa, JDKSAVDECC_FRAME_HEADER_SA_OFFSET );
    }

    ///
    /// \brief getEtherType Get the Frame's EtherType
    /// Note: does not manage tagged frames
    /// \return The EtherType value
    ///
    uint16_t getEtherType() const
    {
        return getDoublet( JDKSAVDECC_FRAME_HEADER_ETHERTYPE_OFFSET );
    }

    ///
    /// \brief setEtherType Set the Frame's EtherType
    /// Note: does not manage tagged frames
    /// \param et The EtherType value
    ///
    void setEtherType( uint16_t et )
    {
        setDoublet( et, JDKSAVDECC_FRAME_HEADER_ETHERTYPE_OFFSET );
    }

    ///
    /// \brief getPayload Get the Frame's Payload
    /// Note: does not manage tagged frames
    /// \return The raw uint8_t pointer to the payload
    ///
    uint8_t *getPayload() { return &m_buf[JDKSAVDECC_FRAME_HEADER_LEN]; }

    ///
    /// \brief getPayload Get The Frame's const Payload
    /// \return The raw uint8_t const pointer to the payload
    ///
    uint8_t const *getPayload() const
    {
        return &m_buf[JDKSAVDECC_FRAME_HEADER_LEN];
    }

    ///
    /// \brief getTimeInMilliseconds Get the timestamp in milliseconds
    /// \return The timestamp
    ///
    jdksavdecc_timestamp_in_milliseconds getTimeInMilliseconds() const
    {
        return m_time_in_ms;
    }

    ///
    /// \brief setTimeInMilliseconds Set the timestamp in milliseconds
    /// \param v The timestamp
    ///
    void setTimeInMilliseconds( jdksavdecc_timestamp_in_milliseconds v )
    {
        m_time_in_ms = v;
    }
};

///
/// \brief The Ethernet FrameWithSize class
///
/// A subclass of Frame which is templatized on a MaxSize
/// argument and allocates a static buffer of that size
///
template <size_t MaxSize=(1500+JDKSAVDECC_FRAME_HEADER_LEN)>
class FrameWithSize : public Frame
{
  protected:
    ///
    /// \brief m_buf_storage The storage for the frame
    ///
    uint8_t m_buf_storage[MaxSize];

  public:
    ///
    /// \brief FrameWithSize Constructor of an empty allocated frame
    ///
    FrameWithSize() : Frame( 0, m_buf_storage, MaxSize ) {}

    ///
    /// \brief FrameWithSize Constructor of an empty frame with timestamp
    /// \param time_in_ms The timestamp in milliseconds
    ///
    FrameWithSize( jdksavdecc_timestamp_in_milliseconds time_in_ms )
        : Frame( time_in_ms, m_buf_storage, MaxSize )
    {
    }

    ///
    /// \brief FrameWithSize Constructor of a frame with header and timestamp
    /// \param time_in_ms The timestamp in milliseconds
    /// \param dest_mac The destination MAC adddress
    /// \param src_mac The source MAC address
    /// \param ethertype The EtherType
    ///
    FrameWithSize( jdksavdecc_timestamp_in_milliseconds time_in_ms,
                   Eui48 const &dest_mac,
                   Eui48 const &src_mac,
                   uint16_t ethertype )
        : Frame(
              time_in_ms, m_buf_storage, MaxSize, dest_mac, src_mac, ethertype )
    {
    }
};
}
<|endoftext|>


<commit_before>#ifndef LODTALK_COLLECTIONS_HPP_
#define LODTALK_COLLECTIONS_HPP_

#include <stddef.h>
#include <string>
#include "Lodtalk/Object.hpp"

namespace Lodtalk
{

/**
 * Collection
 */
class LODTALK_VM_EXPORT Collection: public Object
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * SequenceableCollection
 */
class LODTALK_VM_EXPORT SequenceableCollection: public Collection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * ArrayedCollection
 */
class LODTALK_VM_EXPORT ArrayedCollection: public SequenceableCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * Array
 */
class LODTALK_VM_EXPORT Array: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

	static Array *basicNativeNew(VMContext *context, size_t indexableSize);
};

/**
 * ByteArray
 */
class LODTALK_VM_EXPORT ByteArray: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * FloatArray
 */
class LODTALK_VM_EXPORT FloatArray: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * WordArray
 */
class LODTALK_VM_EXPORT WordArray: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * IntegerArray
 */
class LODTALK_VM_EXPORT IntegerArray: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * String
 */
class LODTALK_VM_EXPORT String: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * ByteString
 */
class LODTALK_VM_EXPORT ByteString: public String
{
public:
    static SpecialNativeClassFactory Factory;

	static ByteString *basicNativeNew(VMContext *context, size_t indexableSize);

	static ByteString *fromNativeRange(VMContext *context, const char *start, size_t size);
    static ByteString *fromNativeReverseRange(VMContext *context, const char *start, ptrdiff_t size);
	static Ref<ByteString> fromNative(VMContext *context, const std::string &native);

	static Oop splitVariableNames(VMContext *context, const std::string &string);

	std::string getString();

    static int stSplitVariableNames(InterpreterProxy *interpreter);
};

/**
 * WideString
 */
class LODTALK_VM_EXPORT WideString: public String
{
public:
    static SpecialNativeClassFactory Factory;
};

/**
 * Symbol
 */
class LODTALK_VM_EXPORT Symbol: public String
{
public:
    static SpecialNativeClassFactory Factory;
};

/**
 * ByteSymbol
 */
class LODTALK_VM_EXPORT ByteSymbol: public Symbol
{
public:
    static SpecialNativeClassFactory Factory;

	static Object *basicNativeNew(VMContext *context, size_t indexableSize);

	static Oop fromNative(VMContext *context, const std::string &native);
	static Oop fromNativeRange(VMContext *context, const char *star, size_t size);

	std::string getString();
};

/**
 * WideSymbol
 */
class LODTALK_VM_EXPORT WideSymbol: public Symbol
{
public:
    static SpecialNativeClassFactory Factory;
};

/**
 * HashedCollection
 */
class LODTALK_VM_EXPORT HashedCollection: public Collection
{
public:
    static SpecialNativeClassFactory Factory;

    void initialize()
    {
        capacityObject = Oop::encodeSmallInteger(0);
        tallyObject = Oop::encodeSmallInteger(0);
        keyValues = (Array*)&NilObject;
    }

	size_t getCapacity() const
	{
		return capacityObject.decodeSmallInteger();
	}

	size_t getTally() const
	{
		return tallyObject.decodeSmallInteger();
	}

	Oop *getHashTableKeyValues() const
	{
		assert(keyValues);
		return reinterpret_cast<Oop*> (keyValues->getFirstFieldPointer());
	}

protected:
	void setKeyCapacity(VMContext *context, size_t keyCapacity)
	{
		keyValues = Array::basicNativeNew(context, keyCapacity);
	}

	template<typename KF, typename HF, typename EF>
	ptrdiff_t findKeyPosition(Oop key, const KF &keyFunction, const HF &hashFunction, const EF &equals)
	{
		auto capacity = getCapacity();
		if(capacity == 0)
			return -1;

		auto keyHash = hashFunction(key);
		auto startPosition = keyHash % capacity;
		auto keyValuesArray = getHashTableKeyValues();

		// Search from the hash position to the end.
		for(auto i = startPosition; i < capacity; ++i)
		{
			// Check no association
			auto keyValue = keyValuesArray[i];
			if(isNil(keyValue))
				return i;

			// Check the key
			auto slotKey = keyFunction(keyValue);
			if(equals(key, slotKey))
				return i;
		}

		// Search from the start to the hash position.
		for(auto i = 0; i < startPosition; ++i)
		{
			// Check no association
			auto keyValue = keyValuesArray[i];
			if(isNil(keyValue))
				return i;

			// Check the key
			auto slotKey = keyFunction(keyValuesArray[i]);
			if(equals(key, slotKey))
				return i;
		}

		// Not found.
		return -1;
	}

	template<typename KF, typename HF, typename EF>
	void increaseSize(VMContext *context, const KF &keyFunction, const HF &hashFunction, const EF &equalityFunction)
	{
		tallyObject.intValue += 2;

		// Do not use more than 80% of the capacity
		if(tallyObject.intValue > capacityObject.intValue*4/5)
			increaseCapacity(context, keyFunction, hashFunction, equalityFunction);
	}

	template<typename KF, typename HF, typename EF>
	void increaseCapacity(VMContext *context, const KF &keyFunction, const HF &hashFunction, const EF &equalityFunction)
	{
		size_t newCapacity = getCapacity()*2;
		if(!newCapacity)
			newCapacity = 16;

		setCapacity(context, newCapacity, keyFunction, hashFunction, equalityFunction);
	}

	template<typename KF, typename HF, typename EF>
	Oop internalKeyValueAtOrNil(Oop key, const KF &keyFunction, const HF &hashFunction, const EF &equalityFunction)
	{
		// If a slot was not found, try to increase the capacity.
		auto position = findKeyPosition(key, keyFunction, hashFunction, equalityFunction);
		if(position < 0)
			return nilOop();

		auto oldKeyValue = getHashTableKeyValues()[position];
		if(isNil(oldKeyValue))
			return nilOop();
		return oldKeyValue;
	}

	template<typename KF, typename HF, typename EF>
	void internalPutKeyValue(VMContext *context, Oop keyValue, const KF &keyFunction, const HF &hashFunction, const EF &equalityFunction)
	{
		// If a slot was not found, try to increase the capacity.
		auto position = findKeyPosition(keyFunction(keyValue), keyFunction, hashFunction, equalityFunction);
		if(position < 0)
		{
            OopRef keyValueRef(context, keyValue);
			increaseCapacity(context, keyFunction, hashFunction, equalityFunction);
			return internalPutKeyValue(context, keyValueRef.oop, keyFunction, hashFunction, equalityFunction);
		}

		// Put the key and value.
		auto keyValueArray = getHashTableKeyValues();
		auto oldKeyValue = keyValueArray[position];
		keyValueArray[position] = keyValue;

		// Increase the size.
		if(isNil(oldKeyValue))
			increaseSize(context, keyFunction, hashFunction, equalityFunction);
	}

	template<typename KF, typename HF, typename EF>
	void setCapacity(VMContext *context, size_t newCapacity, const KF &keyFunction, const HF &hashFunction, const EF &equalityFunction)
	{
		// Store temporarily the data.
		Ref<Array> oldKeyValues(context, keyValues);
		size_t oldCapacity = capacityObject.decodeSmallInteger();

		// Create the new capacity.
		capacityObject = Oop::encodeSmallInteger(newCapacity);
		tallyObject = Oop::encodeSmallInteger(0);
		setKeyCapacity(context, newCapacity);

		// Add back the old objects.
		if(!oldKeyValues.isNil())
		{
			Oop *oldKeyValuesOops = reinterpret_cast<Oop *> (oldKeyValues->getFirstFieldPointer());
			for(size_t i = 0; i < oldCapacity; ++i)
			{
				auto oldKeyValue = oldKeyValuesOops[i];
				if(!isNil(oldKeyValue))
					internalPutKeyValue(context, oldKeyValue, keyFunction, hashFunction, equalityFunction);
			}
		}
	}

	Oop capacityObject;
	Oop tallyObject;
	Array* keyValues;
};

/**
 * Dictionary
 */
class LODTALK_VM_EXPORT Dictionary: public HashedCollection
{
public:
    static SpecialNativeClassFactory Factory;
};

/**
 * MethodDictionary
 */
class LODTALK_VM_EXPORT MethodDictionary: public Dictionary
{
public:
    static SpecialNativeClassFactory Factory;

	static MethodDictionary* basicNativeNew(VMContext *context);

	Oop atOrNil(Oop key)
	{
		return internalAtOrNil(key);
	}

	Oop atPut(VMContext *context, Oop key, Oop value)
	{
		internalAtPut(context, key, value);
		return value;
	}

	Oop *getHashTableKeys() const
	{
		assert(keyValues);
		return reinterpret_cast<Oop*> (keyValues->getFirstFieldPointer());
	}

	Oop *getHashTableValues() const
	{
		assert(values);
		return reinterpret_cast<Oop*> (values->getFirstFieldPointer());
	}

    static int stAtOrNil(InterpreterProxy *interpreter);
    static int stAtPut(InterpreterProxy *interpreter);

protected:
	MethodDictionary()
	{
		object_header_ = ObjectHeader::specialNativeClass(generateIdentityHash(this), SCI_MethodDictionary, 4);
		values = (Array*)&NilObject;
	}

	void increaseSize(VMContext *context)
	{
		tallyObject.intValue += 2;

		// Do not use more than 80% of the capacity
		if(tallyObject.intValue > capacityObject.intValue*4/5)
			increaseCapacity(context);
	}

	void increaseCapacity(VMContext *context)
	{
		size_t newCapacity = getCapacity()*2;
		if(!newCapacity)
			newCapacity = 16;

		setCapacity(context, newCapacity);
	}

	Oop internalAtOrNil(Oop key)
	{
		// If a slot was not found, try to increase the capacity.
		auto position = findKeyPosition(key, identityFunction<Oop>, identityHashOf, identityOopEquals);
		if(position < 0)
			return nilOop();

		auto oldKey = getHashTableKeys()[position];
		if(isNil(oldKey))
			return nilOop();
		return getHashTableValues()[position];
	}

	void internalAtPut(VMContext *context, Oop key, Oop value)
	{
		// If a slot was not found, try to increase the capacity.
		auto position = findKeyPosition(key, identityFunction<Oop>, identityHashOf, identityOopEquals);
		if(position < 0)
		{
            OopRef keyRef(context, key);
            OopRef valueRef(context, value);
			increaseCapacity(context);
            return internalAtPut(context, keyRef.oop, valueRef.oop);
		}

		// Put the key and value.
		auto keyArray = getHashTableKeys();
		auto valueArray = getHashTableValues();
		auto oldKey = keyArray[position];
		keyArray[position] = key;
		valueArray[position] = value;

		// Increase the size.
		if(isNil(oldKey))
			increaseSize(context);
	}

	void setCapacity(VMContext *context, size_t newCapacity)
	{
		// Store temporarily the data.
		Ref<Array> oldKeys(context, keyValues);
		Ref<Array> oldValues(context, values);
		size_t oldCapacity = capacityObject.decodeSmallInteger();

		// Create the new capacity.
		capacityObject = Oop::encodeSmallInteger(newCapacity);
		tallyObject = Oop::encodeSmallInteger(0);
		setKeyCapacity(context, newCapacity);
		setValueCapacity(context, newCapacity);

		// Add back the old objects.
		if(!oldKeys.isNil())
		{
			Oop *oldKeysOops = reinterpret_cast<Oop *> (oldKeys->getFirstFieldPointer());
			Oop *oldValuesOops = reinterpret_cast<Oop *> (oldValues->getFirstFieldPointer());
			for(size_t i = 0; i < oldCapacity; ++i)
			{
				auto oldKey = oldKeysOops[i];
				if(!isNil(oldKey))
					internalAtPut(context, oldKey, oldValuesOops[i]);
			}
		}
	}

	void setValueCapacity(VMContext *context, size_t valueCapacity)
	{
		values = Array::basicNativeNew(context, valueCapacity);
	}

	Array* values;
};

/**
 * IdentityDictionary
 */
class LODTALK_VM_EXPORT IdentityDictionary: public Dictionary
{
public:
    static SpecialNativeClassFactory Factory;

	struct End {};

	Oop putAssociation(VMContext *context, Oop assoc)
	{
		internalPutKeyValue(context, assoc, getLookupKeyKey, identityHashOf, identityOopEquals);
        return assoc;
	}

	Oop getAssociationOrNil(Oop key)
	{
		return internalKeyValueAtOrNil(key, getLookupKeyKey, identityHashOf, identityOopEquals);
	}

	void putNativeAssociation(VMContext *context, Association *assoc)
	{
		putAssociation(context, Oop::fromPointer(assoc));
	}

	Association *getNativeAssociationOrNil(Oop key)
	{
		return reinterpret_cast<Association *> (getAssociationOrNil(key).pointer);
	}

    static int stPutAssociation(InterpreterProxy *interpreter);
    static int stAssociationAtOrNil(InterpreterProxy *interpreter);
};

/**
 * SystemDictionary
 */
class LODTALK_VM_EXPORT SystemDictionary: public IdentityDictionary
{
public:
    static SpecialNativeClassFactory Factory;

	struct End {};

    static SystemDictionary *create(VMContext *context);
};

} // End of namespace Lodtalk

#endif //LODTALK_COLLECTIONS_HPP_
<commit_msg>I just found that some collections that are natively implemented are broken. Garbage collection can change this!<commit_after>#ifndef LODTALK_COLLECTIONS_HPP_
#define LODTALK_COLLECTIONS_HPP_

#include <stddef.h>
#include <string>
#include "Lodtalk/Object.hpp"

namespace Lodtalk
{

/**
 * Collection
 */
class LODTALK_VM_EXPORT Collection: public Object
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * SequenceableCollection
 */
class LODTALK_VM_EXPORT SequenceableCollection: public Collection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * ArrayedCollection
 */
class LODTALK_VM_EXPORT ArrayedCollection: public SequenceableCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * Array
 */
class LODTALK_VM_EXPORT Array: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

	static Array *basicNativeNew(VMContext *context, size_t indexableSize);
};

/**
 * ByteArray
 */
class LODTALK_VM_EXPORT ByteArray: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * FloatArray
 */
class LODTALK_VM_EXPORT FloatArray: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * WordArray
 */
class LODTALK_VM_EXPORT WordArray: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * IntegerArray
 */
class LODTALK_VM_EXPORT IntegerArray: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * String
 */
class LODTALK_VM_EXPORT String: public ArrayedCollection
{
public:
    static SpecialNativeClassFactory Factory;

};

/**
 * ByteString
 */
class LODTALK_VM_EXPORT ByteString: public String
{
public:
    static SpecialNativeClassFactory Factory;

	static ByteString *basicNativeNew(VMContext *context, size_t indexableSize);

	static ByteString *fromNativeRange(VMContext *context, const char *start, size_t size);
    static ByteString *fromNativeReverseRange(VMContext *context, const char *start, ptrdiff_t size);
	static Ref<ByteString> fromNative(VMContext *context, const std::string &native);

	static Oop splitVariableNames(VMContext *context, const std::string &string);

	std::string getString();

    static int stSplitVariableNames(InterpreterProxy *interpreter);
};

/**
 * WideString
 */
class LODTALK_VM_EXPORT WideString: public String
{
public:
    static SpecialNativeClassFactory Factory;
};

/**
 * Symbol
 */
class LODTALK_VM_EXPORT Symbol: public String
{
public:
    static SpecialNativeClassFactory Factory;
};

/**
 * ByteSymbol
 */
class LODTALK_VM_EXPORT ByteSymbol: public Symbol
{
public:
    static SpecialNativeClassFactory Factory;

	static Object *basicNativeNew(VMContext *context, size_t indexableSize);

	static Oop fromNative(VMContext *context, const std::string &native);
	static Oop fromNativeRange(VMContext *context, const char *star, size_t size);

	std::string getString();
};

/**
 * WideSymbol
 */
class LODTALK_VM_EXPORT WideSymbol: public Symbol
{
public:
    static SpecialNativeClassFactory Factory;
};

/**
 * HashedCollection
 */
class LODTALK_VM_EXPORT HashedCollection: public Collection
{
public:
    static SpecialNativeClassFactory Factory;

    void initialize()
    {
        capacityObject = Oop::encodeSmallInteger(0);
        tallyObject = Oop::encodeSmallInteger(0);
        keyValues = (Array*)&NilObject;
    }

	size_t getCapacity() const
	{
		return capacityObject.decodeSmallInteger();
	}

	size_t getTally() const
	{
		return tallyObject.decodeSmallInteger();
	}

	Oop *getHashTableKeyValues() const
	{
		assert(keyValues);
		return reinterpret_cast<Oop*> (keyValues->getFirstFieldPointer());
	}

protected:
	void setKeyCapacity(VMContext *context, size_t keyCapacity)
	{
		keyValues = Array::basicNativeNew(context, keyCapacity);
	}

	template<typename KF, typename HF, typename EF>
	ptrdiff_t findKeyPosition(Oop key, const KF &keyFunction, const HF &hashFunction, const EF &equals)
	{
		auto capacity = getCapacity();
		if(capacity == 0)
			return -1;

		auto keyHash = hashFunction(key);
		auto startPosition = keyHash % capacity;
		auto keyValuesArray = getHashTableKeyValues();

		// Search from the hash position to the end.
		for(auto i = startPosition; i < capacity; ++i)
		{
			// Check no association
			auto keyValue = keyValuesArray[i];
			if(isNil(keyValue))
				return i;

			// Check the key
			auto slotKey = keyFunction(keyValue);
			if(equals(key, slotKey))
				return i;
		}

		// Search from the start to the hash position.
		for(auto i = 0; i < startPosition; ++i)
		{
			// Check no association
			auto keyValue = keyValuesArray[i];
			if(isNil(keyValue))
				return i;

			// Check the key
			auto slotKey = keyFunction(keyValuesArray[i]);
			if(equals(key, slotKey))
				return i;
		}

		// Not found.
		return -1;
	}

	template<typename KF, typename HF, typename EF>
	void increaseSize(VMContext *context, const KF &keyFunction, const HF &hashFunction, const EF &equalityFunction)
	{
		tallyObject.intValue += 2;

		// Do not use more than 80% of the capacity
		if(tallyObject.intValue > capacityObject.intValue*4/5)
			increaseCapacity(context, keyFunction, hashFunction, equalityFunction);
	}

	template<typename KF, typename HF, typename EF>
	void increaseCapacity(VMContext *context, const KF &keyFunction, const HF &hashFunction, const EF &equalityFunction)
	{
		size_t newCapacity = getCapacity()*2;
		if(!newCapacity)
			newCapacity = 16;

		setCapacity(context, newCapacity, keyFunction, hashFunction, equalityFunction);
	}

	template<typename KF, typename HF, typename EF>
	Oop internalKeyValueAtOrNil(Oop key, const KF &keyFunction, const HF &hashFunction, const EF &equalityFunction)
	{
		// If a slot was not found, try to increase the capacity.
		auto position = findKeyPosition(key, keyFunction, hashFunction, equalityFunction);
		if(position < 0)
			return nilOop();

		auto oldKeyValue = getHashTableKeyValues()[position];
		if(isNil(oldKeyValue))
			return nilOop();
		return oldKeyValue;
	}

	template<typename KF, typename HF, typename EF>
	void internalPutKeyValue(VMContext *context, Oop keyValue, const KF &keyFunction, const HF &hashFunction, const EF &equalityFunction)
	{
		// If a slot was not found, try to increase the capacity.
		auto position = findKeyPosition(keyFunction(keyValue), keyFunction, hashFunction, equalityFunction);
		if(position < 0)
		{
            OopRef keyValueRef(context, keyValue);
			increaseCapacity(context, keyFunction, hashFunction, equalityFunction);
			return internalPutKeyValue(context, keyValueRef.oop, keyFunction, hashFunction, equalityFunction);
		}

		// Put the key and value.
		auto keyValueArray = getHashTableKeyValues();
		auto oldKeyValue = keyValueArray[position];
		keyValueArray[position] = keyValue;

		// Increase the size.
		if(isNil(oldKeyValue))
			increaseSize(context, keyFunction, hashFunction, equalityFunction);
	}

	template<typename KF, typename HF, typename EF>
	void setCapacity(VMContext *context, size_t newCapacity, const KF &keyFunction, const HF &hashFunction, const EF &equalityFunction)
	{
		// Store temporarily the data.
		Ref<Array> oldKeyValues(context, keyValues);
		size_t oldCapacity = capacityObject.decodeSmallInteger();

		// Create the new capacity.
		capacityObject = Oop::encodeSmallInteger(newCapacity);
		tallyObject = Oop::encodeSmallInteger(0);
		setKeyCapacity(context, newCapacity);

		// Add back the old objects.
		if(!oldKeyValues.isNil())
		{
			Oop *oldKeyValuesOops = reinterpret_cast<Oop *> (oldKeyValues->getFirstFieldPointer());
			for(size_t i = 0; i < oldCapacity; ++i)
			{
				auto oldKeyValue = oldKeyValuesOops[i];
				if(!isNil(oldKeyValue))
					internalPutKeyValue(context, oldKeyValue, keyFunction, hashFunction, equalityFunction);
			}
		}
	}

	Oop capacityObject;
	Oop tallyObject;
	Array* keyValues;
};

/**
 * Dictionary
 */
class LODTALK_VM_EXPORT Dictionary: public HashedCollection
{
public:
    static SpecialNativeClassFactory Factory;
};

/**
 * MethodDictionary
 */
class LODTALK_VM_EXPORT MethodDictionary: public Dictionary
{
public:
    static SpecialNativeClassFactory Factory;

	static MethodDictionary* basicNativeNew(VMContext *context);

	Oop atOrNil(Oop key)
	{
		return internalAtOrNil(key);
	}

	Oop atPut(VMContext *context, Oop key, Oop value)
	{
		internalAtPut(context, key, value);
		return value;
	}

	Oop *getHashTableKeys() const
	{
		assert(keyValues);
		return reinterpret_cast<Oop*> (keyValues->getFirstFieldPointer());
	}

	Oop *getHashTableValues() const
	{
		assert(values);
		return reinterpret_cast<Oop*> (values->getFirstFieldPointer());
	}

    static int stAtOrNil(InterpreterProxy *interpreter);
    static int stAtPut(InterpreterProxy *interpreter);

protected:
	MethodDictionary()
	{
		object_header_ = ObjectHeader::specialNativeClass(generateIdentityHash(this), SCI_MethodDictionary, 4);
		values = (Array*)&NilObject;
	}

	void increaseSize(VMContext *context)
	{
		tallyObject.intValue += 2;

		// Do not use more than 80% of the capacity
		if(tallyObject.intValue > capacityObject.intValue*4/5)
			increaseCapacity(context);
	}

	void increaseCapacity(VMContext *context)
	{
		size_t newCapacity = getCapacity()*2;
		if(!newCapacity)
			newCapacity = 16;

		setCapacity(context, newCapacity);
	}

	Oop internalAtOrNil(Oop key)
	{
		// If a slot was not found, try to increase the capacity.
		auto position = findKeyPosition(key, identityFunction<Oop>, identityHashOf, identityOopEquals);
		if(position < 0)
			return nilOop();

		auto oldKey = getHashTableKeys()[position];
		if(isNil(oldKey))
			return nilOop();
		return getHashTableValues()[position];
	}

	void internalAtPut(VMContext *context, Oop key, Oop value)
	{
		// If a slot was not found, try to increase the capacity.
		auto position = findKeyPosition(key, identityFunction<Oop>, identityHashOf, identityOopEquals);
		if(position < 0)
		{
            OopRef keyRef(context, key);
            OopRef valueRef(context, value);
            Ref<MethodDictionary> selfRef(context, this);
			increaseCapacity(context);
            return selfRef->internalAtPut(context, keyRef.oop, valueRef.oop);
		}

		// Put the key and value.
		auto keyArray = getHashTableKeys();
		auto valueArray = getHashTableValues();
		auto oldKey = keyArray[position];
		keyArray[position] = key;
		valueArray[position] = value;

		// Increase the size.
		if(isNil(oldKey))
			increaseSize(context);
	}

	void setCapacity(VMContext *context, size_t newCapacity)
	{
		// Store temporarily the data.
		Ref<Array> oldKeys(context, keyValues);
		Ref<Array> oldValues(context, values);
        Ref<MethodDictionary> selfRef(context, this);
		size_t oldCapacity = capacityObject.decodeSmallInteger();

		// Create the new capacity.
		capacityObject = Oop::encodeSmallInteger(newCapacity);
		tallyObject = Oop::encodeSmallInteger(0);
		setKeyCapacity(context, newCapacity);
		setValueCapacity(context, newCapacity);

		// Add back the old objects.
		if(!oldKeys.isNil())
		{
			Oop *oldKeysOops = reinterpret_cast<Oop *> (oldKeys->getFirstFieldPointer());
			Oop *oldValuesOops = reinterpret_cast<Oop *> (oldValues->getFirstFieldPointer());
			for(size_t i = 0; i < oldCapacity; ++i)
			{
				auto oldKey = oldKeysOops[i];
				if(!isNil(oldKey))
					internalAtPut(context, oldKey, oldValuesOops[i]);
			}
		}
	}

	void setValueCapacity(VMContext *context, size_t valueCapacity)
	{
		values = Array::basicNativeNew(context, valueCapacity);
	}

	Array* values;
};

/**
 * IdentityDictionary
 */
class LODTALK_VM_EXPORT IdentityDictionary: public Dictionary
{
public:
    static SpecialNativeClassFactory Factory;

	struct End {};

	Oop putAssociation(VMContext *context, Oop assoc)
	{
		internalPutKeyValue(context, assoc, getLookupKeyKey, identityHashOf, identityOopEquals);
        return assoc;
	}

	Oop getAssociationOrNil(Oop key)
	{
		return internalKeyValueAtOrNil(key, getLookupKeyKey, identityHashOf, identityOopEquals);
	}

	void putNativeAssociation(VMContext *context, Association *assoc)
	{
		putAssociation(context, Oop::fromPointer(assoc));
	}

	Association *getNativeAssociationOrNil(Oop key)
	{
		return reinterpret_cast<Association *> (getAssociationOrNil(key).pointer);
	}

    static int stPutAssociation(InterpreterProxy *interpreter);
    static int stAssociationAtOrNil(InterpreterProxy *interpreter);
};

/**
 * SystemDictionary
 */
class LODTALK_VM_EXPORT SystemDictionary: public IdentityDictionary
{
public:
    static SpecialNativeClassFactory Factory;

	struct End {};

    static SystemDictionary *create(VMContext *context);
};

} // End of namespace Lodtalk

#endif //LODTALK_COLLECTIONS_HPP_
<|endoftext|>


<commit_before>/*! \file bitset.hpp
    \brief Support for types found in \<bitset\>
    \ingroup STLSupport */
/*
  Copyright (c) 2014, Randolph Voorhies, Shane Grant
  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.
      * Neither the name of cereal 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 RANDOLPH VOORHIES OR SHANE GRANT 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.
*/
#ifndef CEREAL_TYPES_BITSET_HPP_
#define CEREAL_TYPES_BITSET_HPP_

#include "cereal/cereal.hpp"
#include "cereal/types/string.hpp"
#include <bitset>

namespace cereal
{
  namespace bitset_detail
  {
    //! The type the bitset is encoded with
    /*! @internal */
    enum class type : uint8_t
    {
      ulong,
      ullong,
      string,
      bits
    };
  }

  //! Serializing (save) for std::bitset when BinaryData optimization supported
  template <class Archive, size_t N,
            traits::EnableIf<traits::is_output_serializable<BinaryData<std::uint32_t>, Archive>::value>
            = traits::sfinae> inline
  void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
  {
    ar( CEREAL_NVP_("type", bitset_detail::type::bits) );

    // Serialize 8 bit chunks
    std::uint8_t chunk = 0;
    std::uint8_t mask = 0x80;

    // Set each chunk using a rotating mask for the current bit
    for( std::size_t i = 0; i < N; ++i )
    {
      if( bits[i] )
        chunk |= mask;

      mask >>= 1;

      // output current chunk when mask is empty (8 bits)
      if( mask == 0 )
      {
        ar( chunk );
        chunk = 0;
        mask = 0x80;
      }
    }

    // serialize remainder, if it exists
    if( mask != 0x80 )
      ar( chunk );
  }

  //! Serializing (save) for std::bitset when BinaryData is not supported
  template <class Archive, size_t N,
            traits::DisableIf<traits::is_output_serializable<BinaryData<std::uint32_t>, Archive>::value>
            = traits::sfinae> inline
  void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
  {
    try
    {
      auto const b = bits.to_ulong();
      ar( CEREAL_NVP_("type", bitset_detail::type::ulong) );
      ar( CEREAL_NVP_("data", b) );
    }
    catch( std::overflow_error const & )
    {
      try
      {
        auto const b = bits.to_ullong();
        ar( CEREAL_NVP_("type", bitset_detail::type::ullong) );
        ar( CEREAL_NVP_("data", b) );
      }
      catch( std::overflow_error const & )
      {
        ar( CEREAL_NVP_("type", bitset_detail::type::string) );
        ar( CEREAL_NVP_("data", bits.to_string()) );
      }
    }
  }

  //! Serializing (load) for std::bitset
  template <class Archive, size_t N> inline
  void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::bitset<N> & bits )
  {
    bitset_detail::type t;
    ar( CEREAL_NVP_("type", t) );

    switch( t )
    {
      case bitset_detail::type::ulong:
      {
        unsigned long b;
        ar( CEREAL_NVP_("data", b) );
        bits = std::bitset<N>( b );
        break;
      }
      case bitset_detail::type::ullong:
      {
        unsigned long long b;
        ar( CEREAL_NVP_("data", b) );
        bits = std::bitset<N>( b );
        break;
      }
      case bitset_detail::type::string:
      {
        std::string b;
        ar( CEREAL_NVP_("data", b) );
        bits = std::bitset<N>( b );
        break;
      }
      case bitset_detail::type::bits:
      {
        // Normally we would use BinaryData to route this at compile time,
        // but doing this at runtime doesn't break any old serialization
        std::uint8_t chunk = 0;
        std::uint8_t mask  = 0;

        // Load one chunk at a time, rotating through the chunk
        // to set bits in the bitset
        for( std::size_t i = 0; i < N; ++i )
        {
          if( mask == 0 )
          {
            ar( chunk );
            mask = 0x80;
          }

          if( chunk & mask )
            bits[i] = 1;
          else
            bits[i] = 0;

          mask >>= 1;
        }
        break;
      }
      default:
        throw Exception("Invalid bitset data representation");
    }
  }
} // namespace cereal

#endif // CEREAL_TYPES_BITSET_HPP_
<commit_msg>Clear all bits first before deserializing, this should be faster than individually clearing them.<commit_after>/*! \file bitset.hpp
    \brief Support for types found in \<bitset\>
    \ingroup STLSupport */
/*
  Copyright (c) 2014, Randolph Voorhies, Shane Grant
  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.
      * Neither the name of cereal 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 RANDOLPH VOORHIES OR SHANE GRANT 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.
*/
#ifndef CEREAL_TYPES_BITSET_HPP_
#define CEREAL_TYPES_BITSET_HPP_

#include "cereal/cereal.hpp"
#include "cereal/types/string.hpp"
#include <bitset>

namespace cereal
{
  namespace bitset_detail
  {
    //! The type the bitset is encoded with
    /*! @internal */
    enum class type : uint8_t
    {
      ulong,
      ullong,
      string,
      bits
    };
  }

  //! Serializing (save) for std::bitset when BinaryData optimization supported
  template <class Archive, size_t N,
            traits::EnableIf<traits::is_output_serializable<BinaryData<std::uint32_t>, Archive>::value>
            = traits::sfinae> inline
  void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
  {
    ar( CEREAL_NVP_("type", bitset_detail::type::bits) );

    // Serialize 8 bit chunks
    std::uint8_t chunk = 0;
    std::uint8_t mask = 0x80;

    // Set each chunk using a rotating mask for the current bit
    for( std::size_t i = 0; i < N; ++i )
    {
      if( bits[i] )
        chunk |= mask;

      mask >>= 1;

      // output current chunk when mask is empty (8 bits)
      if( mask == 0 )
      {
        ar( chunk );
        chunk = 0;
        mask = 0x80;
      }
    }

    // serialize remainder, if it exists
    if( mask != 0x80 )
      ar( chunk );
  }

  //! Serializing (save) for std::bitset when BinaryData is not supported
  template <class Archive, size_t N,
            traits::DisableIf<traits::is_output_serializable<BinaryData<std::uint32_t>, Archive>::value>
            = traits::sfinae> inline
  void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
  {
    try
    {
      auto const b = bits.to_ulong();
      ar( CEREAL_NVP_("type", bitset_detail::type::ulong) );
      ar( CEREAL_NVP_("data", b) );
    }
    catch( std::overflow_error const & )
    {
      try
      {
        auto const b = bits.to_ullong();
        ar( CEREAL_NVP_("type", bitset_detail::type::ullong) );
        ar( CEREAL_NVP_("data", b) );
      }
      catch( std::overflow_error const & )
      {
        ar( CEREAL_NVP_("type", bitset_detail::type::string) );
        ar( CEREAL_NVP_("data", bits.to_string()) );
      }
    }
  }

  //! Serializing (load) for std::bitset
  template <class Archive, size_t N> inline
  void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::bitset<N> & bits )
  {
    bitset_detail::type t;
    ar( CEREAL_NVP_("type", t) );

    switch( t )
    {
      case bitset_detail::type::ulong:
      {
        unsigned long b;
        ar( CEREAL_NVP_("data", b) );
        bits = std::bitset<N>( b );
        break;
      }
      case bitset_detail::type::ullong:
      {
        unsigned long long b;
        ar( CEREAL_NVP_("data", b) );
        bits = std::bitset<N>( b );
        break;
      }
      case bitset_detail::type::string:
      {
        std::string b;
        ar( CEREAL_NVP_("data", b) );
        bits = std::bitset<N>( b );
        break;
      }
      case bitset_detail::type::bits:
      {
        // Normally we would use BinaryData to route this at compile time,
        // but doing this at runtime doesn't break any old serialization
        std::uint8_t chunk = 0;
        std::uint8_t mask  = 0;

        bits.reset();

        // Load one chunk at a time, rotating through the chunk
        // to set bits in the bitset
        for( std::size_t i = 0; i < N; ++i )
        {
          if( mask == 0 )
          {
            ar( chunk );
            mask = 0x80;
          }

          if( chunk & mask )
            bits[i] = 1;

          mask >>= 1;
        }
        break;
      }
      default:
        throw Exception("Invalid bitset data representation");
    }
  }
} // namespace cereal

#endif // CEREAL_TYPES_BITSET_HPP_
<|endoftext|>


<commit_before>#ifndef MOS_CAMERA_H
#define MOS_CAMERA_H

#include <glm/glm.hpp>

namespace mos {

/**
 * @brief The Camera class
 */
class Camera {
public:
  /**
   * @brief Camera
   * @param eye Where the camera is located.
   * @param center Where the camera is centered.
   * @param projection Projection matrix (ortho/perspective).
   * @param up Up direction.
   */
  Camera(const glm::vec3 &position, const glm::vec3 &center,
         const glm::mat4 &projection,
         const glm::vec3 &up = glm::vec3(0.0f, 0.0f, 1.0f));

  /**
   * @brief position
   * @return Position of camera.
   */
  glm::vec3 position() const;

  /**
   * @brief Set position.
   * @param position
   */
  void position(const glm::vec3 &position);

  /**
   * @brief Get center point.
   * @return
   */
  glm::vec3 center() const;

  /**
   * @brief Get center point.
   * @param center
   */
  void center(const glm::vec3 &center);

  /**
   * @brief direction
   * @return
   */
  glm::vec3 direction() const;

  /**
   * @brief Projection matrix.
   */
  glm::mat4 projection;

  /**
   * @brief View matrix.
   */
  glm::mat4 view;

private:
  glm::vec3 up_;
  glm::vec3 center_;
  glm::vec3 position_;
};
}

#endif // MOS_CAMERA_H
<commit_msg>Format.<commit_after>#ifndef MOS_CAMERA_H
#define MOS_CAMERA_H

#include <glm/glm.hpp>

namespace mos {

/**
 * @brief The Camera class
 */
class Camera {
public:
  /**
   * @brief Camera
   * @param eye Where the camera is located.
   * @param center Where the camera is centered.
   * @param projection Projection matrix (ortho/perspective).
   * @param up Up direction.
   */
  Camera(const glm::vec3 &position,
         const glm::vec3 &center,
         const glm::mat4 &projection,
         const glm::vec3 &up = glm::vec3(0.0f, 0.0f, 1.0f));

  /**
   * @brief position
   * @return Position of camera.
   */
  glm::vec3 position() const;

  /**
   * @brief Set position.
   * @param position
   */
  void position(const glm::vec3 &position);

  /**
   * @brief Get center point.
   * @return
   */
  glm::vec3 center() const;

  /**
   * @brief Get center point.
   * @param center
   */
  void center(const glm::vec3 &center);

  /**
   * @brief direction
   * @return
   */
  glm::vec3 direction() const;

  /**
   * @brief Projection matrix.
   */
  glm::mat4 projection;

  /**
   * @brief View matrix.
   */
  glm::mat4 view;

private:
  glm::vec3 up_;
  glm::vec3 center_;
  glm::vec3 position_;
};
}

#endif // MOS_CAMERA_H
<|endoftext|>


<commit_before>/* Helper similar to Python's @c str.join().
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead.
 *
 * Copyright (c) 2000-2021, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this
 * mistake, or contact the author.
 */
#ifndef PQXX_H_SEPARATED_LIST
#define PQXX_H_SEPARATED_LIST

#include "pqxx/compiler-public.hxx"
#include "pqxx/internal/compiler-internal-pre.hxx"

#include <algorithm>
#include <numeric>

#include "pqxx/strconv.hxx"

// TODO: Simplify using std::ranges::range, once we're on C++20.
// TODO: Optimise buffer allocation using C++20 random_access_range.
namespace pqxx
{
/**
 * @defgroup utility Utility functions
 */
//@{

/// Represent sequence of values as a string, joined by a given separator.
/**
 * Use this to turn e.g. the numbers 1, 2, and 3 into a string "1, 2, 3".
 *
 * @param sep separator string (to be placed between items)
 * @param begin beginning of items sequence
 * @param end end of items sequence
 * @param access functor defining how to dereference sequence elements
 */
template<typename ITER, typename ACCESS>
[[nodiscard]] inline std::string
separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
{
  if (end == begin)
    return std::string{};
  auto next{begin};
  ++next;
  if (next == end)
    return to_string(access(begin));

  // From here on, we've got at least 2 elements -- meaning that we need sep.
  using elt_type = strip_t<decltype(access(begin))>;
  using traits = string_traits<elt_type>;

  std::size_t budget{0};
  for (ITER cnt{begin}; cnt != end; ++cnt)
    budget += traits::size_buffer(access(cnt));
  budget +=
    static_cast<std::size_t>(std::distance(begin, end)) * std::size(sep);

  std::string result;
  result.resize(budget);

  char *here{std::data(result)};
  char *stop{here + budget};
  here = traits::into_buf(here, stop, access(begin)) - 1;
  for (++begin; begin != end; ++begin)
  {
    here += sep.copy(here, std::size(sep));
    here = traits::into_buf(here, stop, access(begin)) - 1;
  }
  result.resize(static_cast<std::size_t>(here - std::data(result)));
  return result;
}

/// Render sequence as a string, using given separator between items.
template<typename ITER>
[[nodiscard]] inline std::string
separated_list(std::string_view sep, ITER begin, ITER end)
{
  return separated_list(sep, begin, end, [](ITER i) { return *i; });
}

/// Render items in a container as a string, using given separator.
template<typename CONTAINER>
[[nodiscard]] inline auto
separated_list(std::string_view sep, CONTAINER const &c)
  /*
  Always std::string; necessary because SFINAE doesn't work with the
  contents of function bodies, so the check for iterability has to be in
  the signature.
  */
  -> typename std::enable_if<
    (not std::is_void<decltype(std::begin(c))>::value and
     not std::is_void<decltype(std::end(c))>::value),
    std::string>::type
{
  return separated_list(sep, std::begin(c), std::end(c));
}

/// Render items in a tuple as a string, using given separator.
template<
  typename TUPLE, std::size_t INDEX = 0, typename ACCESS,
  typename std::enable_if<
    (INDEX == std::tuple_size<TUPLE>::value - 1), int>::type = 0>
[[nodiscard]] inline std::string separated_list(
  std::string_view /* sep */, TUPLE const &t, ACCESS const &access)
{
  return to_string(access(&std::get<INDEX>(t)));
}

template<
  typename TUPLE, std::size_t INDEX = 0, typename ACCESS,
  typename std::enable_if<
    (INDEX < std::tuple_size<TUPLE>::value - 1), int>::type = 0>
[[nodiscard]] inline std::string
separated_list(std::string_view sep, TUPLE const &t, ACCESS const &access)
{
  std::string out{to_string(access(&std::get<INDEX>(t)))};
  out.append(sep);
  out.append(separated_list<TUPLE, INDEX + 1>(sep, t, access));
  return out;
}

template<
  typename TUPLE, std::size_t INDEX = 0,
  typename std::enable_if<
    (INDEX <= std::tuple_size<TUPLE>::value), int>::type = 0>
[[nodiscard]] inline std::string
separated_list(std::string_view sep, TUPLE const &t)
{
  // TODO: Optimise allocation.
  return separated_list(sep, t, [](TUPLE const &tup) { return *tup; });
}
//@}
} // namespace pqxx

#include "pqxx/internal/compiler-internal-post.hxx"
#endif
<commit_msg>Comment.<commit_after>/* Helper similar to Python's @c str.join().
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead.
 *
 * Copyright (c) 2000-2021, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this
 * mistake, or contact the author.
 */
#ifndef PQXX_H_SEPARATED_LIST
#define PQXX_H_SEPARATED_LIST

#include "pqxx/compiler-public.hxx"
#include "pqxx/internal/compiler-internal-pre.hxx"

#include <algorithm>
#include <numeric>

#include "pqxx/strconv.hxx"

// TODO: Simplify using std::ranges::range, once we're on C++20.
// TODO: Optimise buffer allocation using C++20 random_access_range/iterator.
namespace pqxx
{
/**
 * @defgroup utility Utility functions
 */
//@{

/// Represent sequence of values as a string, joined by a given separator.
/**
 * Use this to turn e.g. the numbers 1, 2, and 3 into a string "1, 2, 3".
 *
 * @param sep separator string (to be placed between items)
 * @param begin beginning of items sequence
 * @param end end of items sequence
 * @param access functor defining how to dereference sequence elements
 */
template<typename ITER, typename ACCESS>
[[nodiscard]] inline std::string
separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
{
  if (end == begin)
    return std::string{};
  auto next{begin};
  ++next;
  if (next == end)
    return to_string(access(begin));

  // From here on, we've got at least 2 elements -- meaning that we need sep.
  using elt_type = strip_t<decltype(access(begin))>;
  using traits = string_traits<elt_type>;

  std::size_t budget{0};
  for (ITER cnt{begin}; cnt != end; ++cnt)
    budget += traits::size_buffer(access(cnt));
  budget +=
    static_cast<std::size_t>(std::distance(begin, end)) * std::size(sep);

  std::string result;
  result.resize(budget);

  char *here{std::data(result)};
  char *stop{here + budget};
  here = traits::into_buf(here, stop, access(begin)) - 1;
  for (++begin; begin != end; ++begin)
  {
    here += sep.copy(here, std::size(sep));
    here = traits::into_buf(here, stop, access(begin)) - 1;
  }
  result.resize(static_cast<std::size_t>(here - std::data(result)));
  return result;
}

/// Render sequence as a string, using given separator between items.
template<typename ITER>
[[nodiscard]] inline std::string
separated_list(std::string_view sep, ITER begin, ITER end)
{
  return separated_list(sep, begin, end, [](ITER i) { return *i; });
}

/// Render items in a container as a string, using given separator.
template<typename CONTAINER>
[[nodiscard]] inline auto
separated_list(std::string_view sep, CONTAINER const &c)
  /*
  Always std::string; necessary because SFINAE doesn't work with the
  contents of function bodies, so the check for iterability has to be in
  the signature.
  */
  -> typename std::enable_if<
    (not std::is_void<decltype(std::begin(c))>::value and
     not std::is_void<decltype(std::end(c))>::value),
    std::string>::type
{
  return separated_list(sep, std::begin(c), std::end(c));
}

/// Render items in a tuple as a string, using given separator.
template<
  typename TUPLE, std::size_t INDEX = 0, typename ACCESS,
  typename std::enable_if<
    (INDEX == std::tuple_size<TUPLE>::value - 1), int>::type = 0>
[[nodiscard]] inline std::string separated_list(
  std::string_view /* sep */, TUPLE const &t, ACCESS const &access)
{
  return to_string(access(&std::get<INDEX>(t)));
}

template<
  typename TUPLE, std::size_t INDEX = 0, typename ACCESS,
  typename std::enable_if<
    (INDEX < std::tuple_size<TUPLE>::value - 1), int>::type = 0>
[[nodiscard]] inline std::string
separated_list(std::string_view sep, TUPLE const &t, ACCESS const &access)
{
  std::string out{to_string(access(&std::get<INDEX>(t)))};
  out.append(sep);
  out.append(separated_list<TUPLE, INDEX + 1>(sep, t, access));
  return out;
}

template<
  typename TUPLE, std::size_t INDEX = 0,
  typename std::enable_if<
    (INDEX <= std::tuple_size<TUPLE>::value), int>::type = 0>
[[nodiscard]] inline std::string
separated_list(std::string_view sep, TUPLE const &t)
{
  // TODO: Optimise allocation.
  return separated_list(sep, t, [](TUPLE const &tup) { return *tup; });
}
//@}
} // namespace pqxx

#include "pqxx/internal/compiler-internal-post.hxx"
#endif
<|endoftext|>


<commit_before>#pragma once

#include <type_traits>
namespace gcl::mp::type_traits
{
    template <class T>
    struct is_template : std::false_type {};
    template <class... T_args, template <class...> class T>
    struct is_template<T<T_args...>> : std::true_type {};
    template <auto... values, template <auto...> class T>
    struct is_template<T<values...>> : std::true_type {};
    template <class T>
    static inline constexpr auto is_template_v = is_template<T>::value;

    template <typename T, typename = void>
    struct is_complete : std::false_type {};
    template <typename T>
    struct is_complete<T, std::void_t<decltype(sizeof(T))>>
        : std::true_type {};
    template <typename T>
    constexpr static inline auto is_complete_v = is_complete<T>::value;

    template <class T_concrete, template <class...> class T>
    struct is_instance_of : std::false_type {};
    template <template <class...> class T, class... T_args>
    struct is_instance_of<T<T_args...>, T> : std::true_type {};
    template <class T_concrete, template <class...> class T>
    static inline constexpr auto is_instance_of_v = is_instance_of<T_concrete, T>::value;

    template <class T, typename... Args>
    class is_brace_constructible {
        template <typename /*= void*/, typename U, typename... U_args>
        struct impl : std::false_type {};
        template <typename U, typename... U_args>
        struct impl<std::void_t<decltype(U{std::declval<U_args>()...})>, U, U_args...> : std::true_type {};

      public:
        constexpr inline static auto value = impl<std::void_t<>, T, Args...>::value;
    };
    template <class T, typename... Args>
    constexpr static inline auto is_brace_constructible_v = is_brace_constructible<T, Args...>::value;

    template <bool evaluation>
    using if_t = std::conditional_t<evaluation, std::true_type, std::false_type>;
    template <bool evaluation>
    constexpr static inline auto if_v = std::conditional_t<evaluation, std::true_type, std::false_type>::value;
}

#include <bitset>
#include <tuple>
#include <array>
namespace gcl::mp::type_traits
{
    template <template <typename> class trait, typename... Ts>
    struct trait_result {
        constexpr static auto as_bitset_v = []() consteval
        {
            using bitset_type = std::bitset<sizeof...(Ts)>;
            using bitset_initializer_t = unsigned long long;
            bitset_initializer_t value{0};
            return bitset_type{((value = (value << 1 | trait<Ts>::value)), ...)};
        }
        ();

        // see gcl::mp::pack_traits::pack_arguments_as for other expansion/conversions
        template <template <typename...> class T>
        using as_t = T<typename trait<Ts>::type...>;
        template <template <typename...> class T>
        constexpr static auto as_v = T{trait<Ts>::value...};
        using as_tuple_t = as_t<std::tuple>;
        constexpr static auto as_tuple_v = std::tuple{trait<Ts>::value...};
        template <class Int = int>
        using as_integer_sequence = std::integer_sequence<Int, trait<Ts>::value...>;
        // constexpr static auto as_array_v = std::array{trait<Ts>::value...}; // OK with GCC 10.2
        using as_array_t = std::array<std::tuple_element_t<0, decltype(std::tuple{trait<Ts>::value...})>, sizeof...(Ts)>;
        constexpr static auto as_array_v = as_array_t{trait<Ts>::value...};
    };
}

//  tests
namespace gcl::mp::type_traits::tests::is_template
{
    static_assert(gcl::mp::type_traits::is_template_v<std::tuple<int, char>>);
    static_assert(gcl::mp::type_traits::is_template_v<std::string>); // std::basic_string<charT, allocator>
    static_assert(not gcl::mp::type_traits::is_template_v<int>);
}
namespace gcl::mp::type_traits::tests::is_complete
{
    struct complete_type {};
    struct incomplete_type;

    static_assert(gcl::mp::type_traits::is_complete_v<complete_type>);
    static_assert(gcl::mp::type_traits::is_complete_v<int>);
    static_assert(not gcl::mp::type_traits::is_complete_v<incomplete_type>);
}
namespace gcl::mp::type_traits::tests::is_instance_of
{
    static_assert(gcl::mp::type_traits::is_instance_of_v<std::tuple<int, char>, std::tuple>);
    static_assert(not gcl::mp::type_traits::is_instance_of_v<std::tuple<int, char>, std::pair>);
}
namespace gcl::mp::type_traits::tests::is_brace_constructible_v
{
    struct toto {
        int i;
    };
    struct titi {
        explicit titi(int) {}
    };

    static_assert(type_traits::is_brace_constructible_v<toto>);
    static_assert(type_traits::is_brace_constructible_v<toto, int>);
    static_assert(type_traits::is_brace_constructible_v<toto, char>);
    static_assert(not type_traits::is_brace_constructible_v<toto, char*>);
    static_assert(not type_traits::is_brace_constructible_v<titi>);
    static_assert(type_traits::is_brace_constructible_v<titi, int>);
    static_assert(type_traits::is_brace_constructible_v<titi, char>);
    static_assert(not type_traits::is_brace_constructible_v<titi, char*>);
}
namespace gcl::mp::type_traits::tests::if_t
{
    static_assert(std::is_same_v<type_traits::if_t<true>, std::true_type>);
    static_assert(std::is_same_v<type_traits::if_t<false>, std::false_type>);
    static_assert(type_traits::if_v<true> == true);
    static_assert(type_traits::if_v<false> == false);
}
#if __cpp_concepts
#include <concepts>
namespace gcl::mp::type_traits::tests::if_t
{
    // clang-format off
    template <typename T>
    concept is_red_colored = requires(T)
    {
        { T::color == decltype(T::color)::red } -> std::convertible_to<bool>;
        { type_traits::if_t<T::color == decltype(T::color)::red>{}} -> std::same_as<std::true_type>;
    };
    enum colors { red, blue, green };
    struct smthg_blue { constexpr static auto color = colors::blue; };
    struct smthg_red { constexpr static auto color = colors::red; };
    // clang-format on

    static_assert(not is_red_colored<smthg_blue>);
    static_assert(is_red_colored<smthg_red>);
}
#endif

namespace gcl::mp::type_traits::tests::trait_results
{
    template <typename T>
    using is_int = std::is_same<int, T>;
    using results = trait_result<is_int, char, int, bool>;

    // static_assert(decltype(results::as_bitset_v){2UL} == results::as_bitset_v); // std::bitset::operator== is not cx
    constexpr auto expected_result_as_bitset = decltype(results::as_bitset_v){2UL};
    static_assert(expected_result_as_bitset[0] == results::as_bitset_v[0]);
    static_assert(expected_result_as_bitset[1] == results::as_bitset_v[1]);
    static_assert(expected_result_as_bitset[2] == results::as_bitset_v[2]);

    using results_as_tuple = results::as_t<std::tuple>;
    using results_as_tuple_value_type = std::decay_t<decltype(results::as_v<std::tuple>)>;
    static_assert(std::tuple_size_v<results_as_tuple> == std::tuple_size_v<results_as_tuple_value_type>); // clang and clang-cl complain here

    using expected_result_type = std::tuple<
        std::false_type,
        std::true_type,
        std::false_type>;
    static_assert(std::is_same_v<results_as_tuple, expected_result_type>);

    using expected_result_value_type = std::tuple<bool, bool, bool>;
    static_assert(std::is_same_v<results_as_tuple_value_type, expected_result_value_type>);

    using expected_result_as_tuple = std::tuple<std::false_type, std::true_type, std::false_type>;
    static_assert(std::is_same_v<results::as_t<std::tuple>, expected_result_as_tuple>);
    static_assert(std::is_same_v<results::as_integer_sequence<int>, std::integer_sequence<int, 0, 1, 0>>);
    static_assert(results::as_array_v == std::array{false, true, false});

    template <typename... Ts>
    struct type_pack {};
    using results_as_type_pack = results::as_t<type_pack>;
    using expected_result_as_type_pack = type_pack<std::false_type, std::true_type, std::false_type>;
    static_assert(std::is_same_v<results_as_type_pack, expected_result_as_type_pack>);
}
<commit_msg>[mp::type_traits] temporary remove trait_results::as_v test when using Clang/Clang-CL (see issue in comment)<commit_after>#pragma once

#include <type_traits>
namespace gcl::mp::type_traits
{
    template <class T>
    struct is_template : std::false_type {};
    template <class... T_args, template <class...> class T>
    struct is_template<T<T_args...>> : std::true_type {};
    template <auto... values, template <auto...> class T>
    struct is_template<T<values...>> : std::true_type {};
    template <class T>
    static inline constexpr auto is_template_v = is_template<T>::value;

    template <typename T, typename = void>
    struct is_complete : std::false_type {};
    template <typename T>
    struct is_complete<T, std::void_t<decltype(sizeof(T))>>
        : std::true_type {};
    template <typename T>
    constexpr static inline auto is_complete_v = is_complete<T>::value;

    template <class T_concrete, template <class...> class T>
    struct is_instance_of : std::false_type {};
    template <template <class...> class T, class... T_args>
    struct is_instance_of<T<T_args...>, T> : std::true_type {};
    template <class T_concrete, template <class...> class T>
    static inline constexpr auto is_instance_of_v = is_instance_of<T_concrete, T>::value;

    template <class T, typename... Args>
    class is_brace_constructible {
        template <typename /*= void*/, typename U, typename... U_args>
        struct impl : std::false_type {};
        template <typename U, typename... U_args>
        struct impl<std::void_t<decltype(U{std::declval<U_args>()...})>, U, U_args...> : std::true_type {};

      public:
        constexpr inline static auto value = impl<std::void_t<>, T, Args...>::value;
    };
    template <class T, typename... Args>
    constexpr static inline auto is_brace_constructible_v = is_brace_constructible<T, Args...>::value;

    template <bool evaluation>
    using if_t = std::conditional_t<evaluation, std::true_type, std::false_type>;
    template <bool evaluation>
    constexpr static inline auto if_v = std::conditional_t<evaluation, std::true_type, std::false_type>::value;
}

#include <bitset>
#include <tuple>
#include <array>
namespace gcl::mp::type_traits
{
    template <template <typename> class trait, typename... Ts>
    struct trait_result {
        constexpr static auto as_bitset_v = []() consteval
        {
            using bitset_type = std::bitset<sizeof...(Ts)>;
            using bitset_initializer_t = unsigned long long;
            bitset_initializer_t value{0};
            return bitset_type{((value = (value << 1 | trait<Ts>::value)), ...)};
        }
        ();

        // see gcl::mp::pack_traits::pack_arguments_as for other expansion/conversions
        template <template <typename...> class T>
        using as_t = T<typename trait<Ts>::type...>;
        template <template <typename...> class T>
        constexpr static auto as_v = T{trait<Ts>::value...};
        using as_tuple_t = as_t<std::tuple>;
        constexpr static auto as_tuple_v = std::tuple{trait<Ts>::value...};
        template <class Int = int>
        using as_integer_sequence = std::integer_sequence<Int, trait<Ts>::value...>;
        // constexpr static auto as_array_v = std::array{trait<Ts>::value...}; // OK with GCC 10.2
        using as_array_t = std::array<std::tuple_element_t<0, decltype(std::tuple{trait<Ts>::value...})>, sizeof...(Ts)>;
        constexpr static auto as_array_v = as_array_t{trait<Ts>::value...};
    };
}

//  tests
namespace gcl::mp::type_traits::tests::is_template
{
    static_assert(gcl::mp::type_traits::is_template_v<std::tuple<int, char>>);
    static_assert(gcl::mp::type_traits::is_template_v<std::string>); // std::basic_string<charT, allocator>
    static_assert(not gcl::mp::type_traits::is_template_v<int>);
}
namespace gcl::mp::type_traits::tests::is_complete
{
    struct complete_type {};
    struct incomplete_type;

    static_assert(gcl::mp::type_traits::is_complete_v<complete_type>);
    static_assert(gcl::mp::type_traits::is_complete_v<int>);
    static_assert(not gcl::mp::type_traits::is_complete_v<incomplete_type>);
}
namespace gcl::mp::type_traits::tests::is_instance_of
{
    static_assert(gcl::mp::type_traits::is_instance_of_v<std::tuple<int, char>, std::tuple>);
    static_assert(not gcl::mp::type_traits::is_instance_of_v<std::tuple<int, char>, std::pair>);
}
namespace gcl::mp::type_traits::tests::is_brace_constructible_v
{
    struct toto {
        int i;
    };
    struct titi {
        explicit titi(int) {}
    };

    static_assert(type_traits::is_brace_constructible_v<toto>);
    static_assert(type_traits::is_brace_constructible_v<toto, int>);
    static_assert(type_traits::is_brace_constructible_v<toto, char>);
    static_assert(not type_traits::is_brace_constructible_v<toto, char*>);
    static_assert(not type_traits::is_brace_constructible_v<titi>);
    static_assert(type_traits::is_brace_constructible_v<titi, int>);
    static_assert(type_traits::is_brace_constructible_v<titi, char>);
    static_assert(not type_traits::is_brace_constructible_v<titi, char*>);
}
namespace gcl::mp::type_traits::tests::if_t
{
    static_assert(std::is_same_v<type_traits::if_t<true>, std::true_type>);
    static_assert(std::is_same_v<type_traits::if_t<false>, std::false_type>);
    static_assert(type_traits::if_v<true> == true);
    static_assert(type_traits::if_v<false> == false);
}
#if __cpp_concepts
#include <concepts>
namespace gcl::mp::type_traits::tests::if_t
{
    // clang-format off
    template <typename T>
    concept is_red_colored = requires(T)
    {
        { T::color == decltype(T::color)::red } -> std::convertible_to<bool>;
        { type_traits::if_t<T::color == decltype(T::color)::red>{}} -> std::same_as<std::true_type>;
    };
    enum colors { red, blue, green };
    struct smthg_blue { constexpr static auto color = colors::blue; };
    struct smthg_red { constexpr static auto color = colors::red; };
    // clang-format on

    static_assert(not is_red_colored<smthg_blue>);
    static_assert(is_red_colored<smthg_red>);
}
#endif

namespace gcl::mp::type_traits::tests::trait_results
{
    template <typename T>
    using is_int = std::is_same<int, T>;
    using results = trait_result<is_int, char, int, bool>;

    // static_assert(decltype(results::as_bitset_v){2UL} == results::as_bitset_v); // std::bitset::operator== is not cx
    constexpr auto expected_result_as_bitset = decltype(results::as_bitset_v){2UL};
    static_assert(expected_result_as_bitset[0] == results::as_bitset_v[0]);
    static_assert(expected_result_as_bitset[1] == results::as_bitset_v[1]);
    static_assert(expected_result_as_bitset[2] == results::as_bitset_v[2]);

    using results_as_tuple = results::as_t<std::tuple>;
    using results_as_tuple_value_type = std::decay_t<decltype(results::as_v<std::tuple>)>;

    #if not defined(__clang__)
    // See my Q on SO :
    //  https://stackoverflow.com/questions/66821952/clang-error-implicit-instantiation-of-undefined-template-stdtuple-sizeauto/66822584
    static_assert(std::tuple_size_v<results_as_tuple> == std::tuple_size_v<results_as_tuple_value_type>); // clang and clang-cl complain here

    using expected_result_type = std::tuple<
        std::false_type,
        std::true_type,
        std::false_type>;
    static_assert(std::is_same_v<results_as_tuple, expected_result_type>);
    using expected_result_value_type = std::tuple<bool, bool, bool>;
    static_assert(std::is_same_v<results_as_tuple_value_type, expected_result_value_type>);
    #endif

    using expected_result_as_tuple = std::tuple<std::false_type, std::true_type, std::false_type>;
    static_assert(std::is_same_v<results::as_t<std::tuple>, expected_result_as_tuple>);
    static_assert(std::is_same_v<results::as_integer_sequence<int>, std::integer_sequence<int, 0, 1, 0>>);
    static_assert(results::as_array_v == std::array{false, true, false});

    template <typename... Ts>
    struct type_pack {};
    using results_as_type_pack = results::as_t<type_pack>;
    using expected_result_as_type_pack = type_pack<std::false_type, std::true_type, std::false_type>;
    static_assert(std::is_same_v<results_as_type_pack, expected_result_as_type_pack>);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include"Pessoa.h"
#include"Bdados.h"
#include"Aluno.h"
using namespace std;
/*******************************************************************************************/
/*******************************************************************************************/
/*******************************************************************************************/

int main(void)
{

	cout << "Development test area!" << endl;

	cout << endl;
	/////////////////////////BDADODS

	string utilizador = "B6_5";
	string palavra = "xico";
	string bd = "193.136.62.27:1521/pdborcl"; //ou em vez de ip, gandalf
	try {
		cout << "Exemplo de ligacao: a ligar ..." << endl;
		BDados *ligacao = new BDados(utilizador, palavra, bd);
		cout << "ligaao estabelecida" << endl;
		delete ligacao;

	}
	catch (SQLException erro) {
		cerr << "Erro: " << erro.getMessage() << endl;
	}

	return 0;
}

	 void janelaLogin()
	 {
		 cout << "######## UC Manager ########" << endl << endl;
		 cout << "Digite nome de utilizador: ";
		 string _user;
		 string _pw;
		 cin  >> _user;
		 cout << endl << "Password: ";
		 cin >> _pw;
	 }

	 void janelaBV_Regente() //janela boas vindas
	 {
		 system("cls");
		 cout << "---Bem-vindo--" << endl << endl <<
			 "1-Entrar UC" << endl << "2-Adicionar UC" << endl << "3-Remover UC" << endl << "A sua opcao:" << endl;
		 char opc;
		 cin >> opc;
		 if (opc > '3' || opc < '0')
		 {
			 janelaBV_Regente();
		 }
	 }

	 void janelaGerirConteudo()
	 {
		 char opc;
		 system("cls");
		 cout << "-----Gerir Conteudos-----" << endl << endl << "0-Voltar" << endl <<
			 "1-Gerir Eventos" << endl << "2-Gerir Docentes" << endl << "3-Gerir UC" << endl << "4-Gerir Alunos" << endl << "A susa opcao: " << endl;
		 if (opc == '0')
		 {
			 janelaBV();
		 }
		 if (opc == '4' || opc == '2' || opc == '3')
		 {
			 // abre janela
		 }
		 if (opc == '1')
		 {

		 }
	 }

		 void janelaGerirEventos()
		 {
			 char opc;
			 system("cls");
			 cout << "-----Gerir Eventos-----" << endl << endl << "0-Voltar" << endl <<
				 "1-Alterar" << endl << "2-Remover" << endl << "3-Adicionar" << endl << "A sua opcao: " << endl;
			 if (opc == '0')
			 {
				 janelaGerirConteudo();
			 }
		}

		 void janelaUC()
		 {
			 char opc;
			 system("cls");
			 cout << "-----Janela UC-----" << endl << endl << "0-Voltar" << endl <<
				 "Leccionadas" << endl << "Permisses/Histrico" << endl;
			 if (opc == '0')
			 {
				 // volta atras
			 }
		 }
		 void janelaMensagens()
		 {
			 char opc;
			 system("cls");
			 cout << "-----Mensagens-----" << endl << endl << "0-Voltar" << endl <<
				 "1-Caixa de entrada" << endl << "2-Escrever mensagem" << endl << "A sua opcao: " << endl;
			 if (opc == '0')
			 {
				 janelaUC();
			 }
		 }

		 void janelaDisciplina()
		 {
			 char opc;
			 system("cls");
			 cout << "-----Gesto Disciplina-----" << endl << endl << "0-Voltar" << endl <<
				 "1-Marcar Avaliacao" << endl << "2-Publicar notas" << endl << "3-Visualizar notas" << endl << "4-Escrever sumarios" << endl  << "5-Visualizar Sumarios"
				 << endl << "6-Marcar aula extra" <<endl<< "7-Histrico"<<endl<< "A sua opcao: " << endl;
			 if (opc == '0')
			 {
				 janelaUC();
			 }
		 }

		 void janelaVisualizacao()

		 {
			 char opc;
			 system("cls");
			 cout << "-----Visualizacao-----" << endl << endl << "0-Voltar" << endl <<
				 "1-Visualizar notas" << endl << "2-Visualizar sumarios" << endl << "A sua opcao: " << endl;
			 if (opc == '0')
			 {
				 janelaUC();
			 }
		 }

		 void janelaCaixaEntrada() // caixa de entrada de mensagens

		 {
			 char opc;
			 system("cls");
			 cout << "-----Caixa de entrada-----" << endl;
			 // falta completar
		 }

		 void janelaEnviarMensagem() // enviar mensagem

		 {
			 char opc;
			 system("cls");
			 cout << "-----Enviar mensagem-----" << endl;
			 // falta completar
		 }

		 void janelaMensagemRecebida() // ler mensagem

		 {
			 char opc;
			 system("cls");
			 cout << "-----Mensagem-----" << endl;
			 // falta completar
		 }

<commit_msg>Ivo Padrão e Afonso Reis - Menu corrigido 8D<commit_after>#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include"Pessoa.h"
#include"Bdados.h"
#include"Aluno.h"
using namespace std;
/*******************************************************************************************/
/*******************************************************************************************/
/*******************************************************************************************/

void janelaLogin();
void janelaBV_Regente();
void janelaMensagens();
void janelaGerirConteudo();
void janelaDisciplina();
void janelaCaixaEntrada();
void janelaEnviarMensagem();
void janelaVisualizacao();
void janelaGerirEventos();

int main(void)
{
	system( "color 79" );
	cout << "Development test area!" << endl;

	cout << endl;
	/////////////////////////BDADODS

	string utilizador = "B6_5";
	string palavra = "xico";
	string bd = "193.136.62.27:1521/pdborcl"; //ou em vez de ip, gandalf
	try {
		cout << "Exemplo de ligacao: a ligar ..." << endl;
		BDados *ligacao = new BDados(utilizador, palavra, bd);
		cout << "ligaao estabelecida" << endl;
		cout << endl << endl << "Prima enter para continuar" << endl;
		char cont;
		cin >> cont;
		delete ligacao;

	}
	catch (SQLException erro) {
		cerr << "Erro: " << erro.getMessage() << endl;
	}
	system("cls");
	janelaLogin();
	return 0;
}

	 void janelaLogin()
	 {
		 cout << "######## UC Manager ########" << endl << endl;
		 cout << "Digite nome de utilizador: ";
		 string _user;
		 string _pw;
		 cin  >> _user;
		 cout << endl << "Password: ";
		 cin >> _pw;

		janelaBV_Regente();
	 }

	 void janelaBV_Regente() //janela boas vindas
	 {
		 system("cls");
		 cout << "-----Bem-vindo-----" << endl << endl <<
			 "1-Entrar UC" << endl << "2-Adicionar UC" << endl << "3-Remover UC"<<endl <<"----------"
			 <<endl <<"m-Mensagens"<< endl << endl << "A sua opcao:" << endl;
		 char opc;
		 cin >> opc;
		 switch (opc)
		 {
			 case '1':janelaGerirConteudo();
			 case '2':
			 case '3':
			 case 'm':janelaMensagens();
			default: janelaGerirConteudo();

		 }

	 }

	 void janelaGerirConteudo()
	 {
		 char opc;
		 system("cls");
		 cout << "-----Gerir Conteudos-----" << endl << endl << "0-Voltar" << endl <<
			 "1-Gerir Eventos" << endl << "2-Gerir Docentes" << endl << "3-Gerir UC" << endl << "4-Gerir Alunos" << endl << "A sua opcao: " << endl;
		 cin >> opc;
		 switch (opc)
		 {
			 case '0':janelaBV_Regente();
			 case '1':janelaGerirEventos();
			 case '2'://janelaGerirDocentes()/
				 ;
			 case '3':
			 case '4':
			 case 'm':janelaMensagens();
			 default: janelaGerirConteudo();
		 }
	 }

		 void janelaGerirEventos()
		 {
			 char opc;
			 system("cls");
			 cout << "-----Gerir Eventos-----" << endl << endl << "0-Voltar" << endl <<
				 "1-Alterar" << endl << "2-Remover" << endl << "3-Adicionar" << endl << "A sua opcao: " << endl;

			cin >> opc;
		 switch (opc)
		 {
			case '0':janelaGerirConteudo();
			 case '1':janelaGerirEventos();
			 case '2'://janelaGerirDocentes()/
				 ;
			 case '3':
			 case '4':
			 case 'm':janelaMensagens();
			 default: janelaGerirEventos();
		 }
		}

		 void janelaUC()
		 {
			 char opc;
			 system("cls");
			 cout << "-----Janela UC-----" << endl << endl << "0-Voltar" << endl <<
				 "1-Leccionadas" << endl << "2-Permissoes/Historico" << endl;
			 cin >> opc;
		 switch (opc)
		 {
			case '0':janelaUC();
			case '1':janelaDisciplina();
			case '2':janelaVisualizacao();
			case '3':;
			case '4':;
			case 'm':janelaMensagens();
			 default: janelaUC();
		 }
		 }
		 void janelaMensagens()
		 {
			 char opc;
			 system("cls");
			 cout << "-----Mensagens-----" << endl << endl << "0-Voltar" << endl <<
				 "1-Caixa de entrada" << endl << "2-Escrever mensagem" << endl << "A sua opcao: " << endl;
			 cin >> opc;
			 switch (opc)
			 {
				case '0':janelaUC();
				case '1':janelaCaixaEntrada();
				case '2':janelaEnviarMensagem();
			 case '3':;
			 case '4':;
			 case 'm':janelaMensagens();
			 default: janelaMensagens();
		 }
		 }

		 void janelaDisciplina()
		 {
			 char opc;
			 system("cls");
			 cout << "-----Gesto Disciplina-----" << endl << endl << "0-Voltar" << endl <<
				 "1-Marcar Avaliacao" << endl << "2-Publicar notas" << endl << "3-Visualizar notas" << endl << "4-Escrever sumarios" << endl  << "5-Visualizar Sumarios"
				 << endl << "6-Marcar aula extra" <<endl<< "7-Histrico"<<endl<< "A sua opcao: " << endl;
			 cin >> opc;
		 switch (opc)
		 {
			case '0':;
			 case '1':;
			 case '2':;
			 case '3':;
			 case '4':;
			 case 'm':;
			 default: janelaUC();
		 }
		 }

		 void janelaVisualizacao()

		 {
			 char opc;
			 system("cls");
			 cout << "-----Visualizacao-----" << endl << endl << "0-Voltar" << endl <<
				 "1-Visualizar notas" << endl << "2-Visualizar sumarios" << endl << "A sua opcao: " << endl;
			 cin >> opc;
		 switch (opc)
		 {
			 case '0':janelaUC();
			 case '1':;
			 case '2':;
			 case '3':;
			 case '4':;
			 case 'm':janelaMensagens();
			 default: janelaVisualizacao();
		 }
		 }

		 void janelaCaixaEntrada() // caixa de entrada de mensagens

		 {
			 char opc;
			 system("cls");
			 cout << "-----Caixa de entrada-----" << endl;
			 // falta completar
		 }

		 void janelaEnviarMensagem() // enviar mensagem

		 {
			 char opc;
			 system("cls");
			 cout << "-----Enviar mensagem-----" << endl;
			 // falta completar
		 }

		 void janelaMensagemRecebida() // ler mensagem

		 {
			 char opc;
			 system("cls");
			 cout << "-----Mensagem-----" << endl;
			 // falta completar
		 }

<|endoftext|>


<commit_before>#include "menu.h"

using namespace std;
using namespace curses;

namespace wano {
	Menu::Menu(EventQueue* eq) :
		win(1, 0, 0, 0),
		items(),
		eq{ eq },
		docx{ 1 },
		docy{ 1 }
	{
		items.push_back(MenuItem("&File"));
		items.push_back(MenuItem("&Edit"));
		items.push_back(MenuItem("F&ormat"));
		items.push_back(MenuItem("&View"));
		items.push_back(MenuItem("&Help"));

		eq->addHandler<coord>(DOC_MOVE, [this](coord c) {
			this->updatePos(c.y + 1, c.x + 1);
		});
	}

	const Window& Menu::getWindow() {
		return win;
	}

	void Menu::draw() {
		win.move(0, 0);
		win.clrToEOL();
		// Menu Color
		Color::InitPair(1, Color::BLACK, Color::CYAN);
		// Hotkey letter color
		Color::InitPair(2, Color::RED, Color::CYAN);
		win.attrOn(Color::Pair(1));
		win.addCh(' ');
		for (const auto& i : items) {
			i.draw(win);
			win.addCh(' ');
		}
		// TODO: This is disgusting but I need it for further textarea work
		char buf[15];
		int len = sprintf_s(buf, "Ln %d, Col %d", docy, docx);
		int numSpaces = win.getMaxX() - (len + win.getX() + 1);
		for (int i = 0; i < numSpaces; i++) {
			win.addCh(' ');
		}
		for (int i = 0; i < len; i++) {
			win.addCh(buf[i]);
		}
		// Insert the last character to keep the cursor from moving and thus
		// going out of bounds
		win.insCh(' ');

		win.attrOff(Color::Pair(1));
		win.refresh();
	}

	void Menu::updatePos(const int ln, const int col) {
		docy = ln;
		docx = col;
		this->draw();
	}
}<commit_msg>One last clang fix: changed `sprintf_s()` in menu.cpp to `snprintf()`<commit_after>#include "menu.h"

using namespace std;
using namespace curses;

namespace wano {
	Menu::Menu(EventQueue* eq) :
		win(1, 0, 0, 0),
		items(),
		eq{ eq },
		docx{ 1 },
		docy{ 1 }
	{
		items.push_back(MenuItem("&File"));
		items.push_back(MenuItem("&Edit"));
		items.push_back(MenuItem("F&ormat"));
		items.push_back(MenuItem("&View"));
		items.push_back(MenuItem("&Help"));

		eq->addHandler<coord>(DOC_MOVE, [this](coord c) {
			this->updatePos(c.y + 1, c.x + 1);
		});
	}

	const Window& Menu::getWindow() {
		return win;
	}

	void Menu::draw() {
		win.move(0, 0);
		win.clrToEOL();
		// Menu Color
		Color::InitPair(1, Color::BLACK, Color::CYAN);
		// Hotkey letter color
		Color::InitPair(2, Color::RED, Color::CYAN);
		win.attrOn(Color::Pair(1));
		win.addCh(' ');
		for (const auto& i : items) {
			i.draw(win);
			win.addCh(' ');
		}
		// TODO: This is disgusting but I need it for further textarea work
		char buf[15];
		int len = snprintf(buf, 15, "Ln %d, Col %d", docy, docx);
		int numSpaces = win.getMaxX() - (len + win.getX() + 1);
		for (int i = 0; i < numSpaces; i++) {
			win.addCh(' ');
		}
		for (int i = 0; i < len; i++) {
			win.addCh(buf[i]);
		}
		// Insert the last character to keep the cursor from moving and thus
		// going out of bounds
		win.insCh(' ');

		win.attrOff(Color::Pair(1));
		win.refresh();
	}

	void Menu::updatePos(const int ln, const int col) {
		docy = ln;
		docx = col;
		this->draw();
	}
}<|endoftext|>