Click here to Skip to main content
15,885,546 members

Bugs and Suggestions

   

General discussions, site bug reports and suggestions about the site.

For general questions check out the CodeProject FAQs. To report spam and abuse Head to the Spam and abuse watch. If you wish to report a bug privately, especially those related to security, please email webmaster@codeproject.com

 
GeneralRe: C++ code formatting problems Pin
Espen Harlinn18-Jun-21 5:54
professionalEspen Harlinn18-Jun-21 5:54 
GeneralRe: C++ code formatting problems Pin
Espen Harlinn18-Jun-21 6:08
professionalEspen Harlinn18-Jun-21 6:08 
GeneralRe: C++ code formatting problems Pin
honey the codewitch18-Jun-21 18:58
mvahoney the codewitch18-Jun-21 18:58 
GeneralRe: C++ code formatting problems Pin
Espen Harlinn19-Jun-21 4:21
professionalEspen Harlinn19-Jun-21 4:21 
AdminRe: C++ code formatting problems Pin
Chris Maunder21-Jun-21 13:46
cofounderChris Maunder21-Jun-21 13:46 
GeneralRe: C++ code formatting problems Pin
Espen Harlinn21-Jun-21 15:01
professionalEspen Harlinn21-Jun-21 15:01 
GeneralRe: C++ code formatting problems Pin
Chris Maunder25-Jun-21 8:06
cofounderChris Maunder25-Jun-21 8:06 
GeneralRe: C++ code formatting problems Pin
Espen Harlinn25-Jun-21 12:12
professionalEspen Harlinn25-Jun-21 12:12 
Here is the contents of a header file that seems to be causing some problems, as the preview does not show anything at all:
C++
#pragma once
#ifndef __HCCPERSISTENT_H__
#define __HCCPERSISTENT_H__

#include <HCCArray.h>
#include <HCCTuple.h>
#include <HCCVector.h>

#pragma pack(push,1)

namespace Harlinn::Common::Core::Persistent
{
    class TypeDescriptorCursor;

    /// <summary>
    /// A sequence is a variable length encoding where data of the same type
    /// is stored in blocks. Each block is of the same size (SequenceBlockSize = 8)
    /// and is trailed by a byte holding the number of used slots in the 
    /// preceding block. The space not used by an element inside a bloc must
    /// be set to 0. A sequence ends with the first block that is not full, thus
    /// an empty sequence contains one block with all the bytes set to 0 and the
    /// trailing size byte set to 0.
    /// </summary>
    constexpr size_t SequenceBlockSize = 8;

    /// <summary>
    /// The minimum number of bytes required to hold a valid
    /// type description
    /// </summary>
    constexpr size_t MinimumValidTypeDescriptorDataSize = 4;

    enum class ModifierFlags : Byte
    {
        None,
        /// <summary>
        /// Indicates that type element is for an array of data. 
        /// </summary>
        /// <remarks>
        /// <p>
        /// If used without the ::Fixed modifier, the data representation
        /// starts with a 7-bit encoded number specifying the number of elements
        /// in the array.
        /// </p>
        /// <p>
        /// If used with the ::Fixed modifier the lenght of the fixed-size
        /// follows immedeately after the TypeElementHeader as a 7-bit 
        /// encoded number.
        /// </p>
        /// </remarks>
        Array = 0x01,
        /// <summary>
        /// Indicates a fixed number of elements
        /// </summary>
        Fixed = 0x02,
        /// <summary>
        /// Constant data trails the declaring type description element.
        /// </summary>
        /// <remarks>
        /// If used together with the ::Array modifier, then the
        /// ::Fixed modifier must also be specified.
        /// </remarks>
        Constant = 0x04,
        /// <summary>
        /// Indicates that the data is stored in big-endian
        /// format.
        /// </summary>
        BigEndian = 0x08,
        /// <summary>
        /// Indicates that the data is encoded in a way that allows ordering between
        /// elements to be established using memcmp.
        /// </summary>
        /// <remarks>
        /// The ::Sequence modifier requires that the ::BigEndian modifier
        /// is also specified. 
        /// </remarks>
        Sequence = 0x10
    };
    HCC_DEFINE_ENUM_FLAG_OPERATORS( ModifierFlags, Byte );


    template<typename T>
    class Constant;

    namespace Internal
    {
        template<typename T>
        constexpr bool IsConstantImpl = false;

        template<typename T>
        constexpr bool IsConstantImpl<Constant<T>> = true;
    }
    template<typename T>
    constexpr bool IsConstant = Persistent::Internal::IsConstantImpl<std::remove_cvref_t<T>>;






    


    namespace Internal
    {
        template<typename T>
        struct FormatTraits;

        template<typename T, typename RT>
        struct FormatTraitsBase
        {
            using Type = T;
            using RawType = RT;
            using TypeTraits = Types::TypeTraits<T>;

            static constexpr bool IsSupported = true;
            static constexpr bool IsFixedSize = TypeTraits::IsFixedSize;

            static constexpr size_t BufferSize( const T& object ) noexcept
            {
                return sizeof( TypeTraits::Type );
            }

            template<typename Writer>
            static constexpr void Write( Writer& writer, const T& object )
            {
                writer.Write( object );
            }
            template<typename Reader>
            static constexpr void Read( Reader& reader, T& object )
            {
                reader.Read( object );
            }

        };


        template<typename T, typename RT>
        struct UnsupportedFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T,RT>;
            static constexpr bool IsSupported = false;
        };

        template<typename T, typename RT>
        struct BasicFormatTraits : FormatTraitsBase<T,RT>
        {
            using Base = FormatTraitsBase<T,RT>;
            using Base::TypeTraits;

            static constexpr Types::BasicTypeId TypeId = TypeTraits::TypeId;

            using FormatType = Tuple<Types::BasicTypeId, ModifierFlags>;
            static constexpr FormatType Format{ TypeId, ModifierFlags::None };

            using DescriptorType = Tuple<Byte, Byte, Types::BasicTypeId, ModifierFlags>;
            static constexpr DescriptorType Descriptor{ static_cast<Byte>('\x2'),static_cast<Byte>('\x1') ,TypeId, ModifierFlags::None};
        };

        template<UInt64 uint64Value>
        struct SevenBitEncodedValue
        {
            static constexpr size_t SizeOfEncodedValue = Core::SizeOf7BitEncodedValue( uint64Value );
            using ValueType = ByteArray<SizeOfEncodedValue>;
            using type = ValueType;
        private:
            static constexpr ValueType Encode( ) noexcept
            {
                ValueType result;
                result.Write7BitEncoded_( 0, uint64Value );

                return result;
            }
        public:
            static constexpr ValueType value = Encode( );
        };


        template<typename T, typename RT>
        struct BasicArrayFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T,RT>;

            using Base::TypeTraits;
            static constexpr UInt64 Count = TypeTraits::Count;

            using ElementType = typename TypeTraits::ElementType;
            using ElementTypeTraits = Types::TypeTraits<ElementType>;
            static constexpr Types::BasicTypeId TypeId = ElementTypeTraits::TypeId;

            static constexpr auto Format = MakeTuple( TypeId, ModifierFlags::Array | ModifierFlags::Fixed, SevenBitEncodedValue<Count>::value );
            using FormatType = decltype( Format );

            static constexpr auto Descriptor = TupleCat(MakeTuple( SevenBitEncodedValue<sizeof( FormatType )>::value, static_cast<Byte>( '\x1' ) ), Format );
            using DescriptorType = decltype( Descriptor );

            static constexpr size_t BufferSize( const T& object ) noexcept
            {
                return TypeTraits::SizeOf( object );
            }

            template<typename Writer>
            static constexpr void Write( Writer& writer, const T& object )
            {
                for ( UInt64 i = 0; i < Count; ++i )
                {
                    writer.Write( object[i] );
                }
            }
            template<typename Reader>
            static constexpr void Read( Reader& reader, T& object )
            {
                for ( UInt64 i = 0; i < Count; ++i )
                {
                    reader.Read( object[i] );
                }
            }


        };





        template<typename T, typename RT>
        struct ArrayFormatTraits : BasicArrayFormatTraits<T, RT>
        {
            

        };

        template<typename T, typename RT>
        struct PointerFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T, RT>;
        };

        template<typename T, typename RT>
        struct ContainerFormatTraitsBase : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T, RT>;
            using Base::TypeTraits;
        };

        template<typename T, typename RT>
        struct ArrayContainerFormatTraits : ContainerFormatTraitsBase<T, RT>
        {
            using Base = ContainerFormatTraitsBase<T, RT>;
            using Base::TypeTraits;
            
        private:
            using ElementType = typename TypeTraits::ElementType;
            using ElementTypeTraits = Types::TypeTraits<ElementType>;

            static constexpr size_t Count = TypeTraits::Count;

            static constexpr auto EvalTypeId( )
            {
                if constexpr ( ElementTypeTraits::IsBasic )
                {
                    return ElementTypeTraits::TypeId;
                }
                else
                {
                    return TypeTraits::TypeId;
                }
            }
            static constexpr auto TypeId = EvalTypeId( );

            static constexpr auto EvalFormat( )
            {
                if constexpr ( ElementTypeTraits::IsBasic )
                {
                    return MakeTuple( TypeId, ModifierFlags::Array | ModifierFlags::Fixed, SevenBitEncodedValue<Count>::value );
                }
                else
                {
                    auto elementDescriptor = FormatTraits<ElementType>::Descriptor;
                    return MakeTuple( TypeId, ModifierFlags::Array | ModifierFlags::Fixed, elementDescriptor, SevenBitEncodedValue<Count>::value );
                }
            }
        public:
            static constexpr auto Format = EvalFormat( );
            using FormatType = decltype( Format );

            static constexpr auto Descriptor = TupleCat( MakeTuple( SevenBitEncodedValue<sizeof( FormatType )>::value, static_cast<Byte>( '\x1' ) ), Format );
            using DescriptorType = decltype( Descriptor );


            static constexpr size_t BufferSize( const T& object ) noexcept
            {
                if constexpr ( Types::IsFixedSize<ElementType>::value )
                {
                    return Count * Types::PackedSizeOf<T>::value;
                }
                else
                {
                    using ElementTypeFormatTraits = FormatTraits<ElementType>;

                    size_t result = 0;
                    for ( size_t i = 0; i < Count; ++i )
                    {
                        const auto& item = object[i];
                        result += ElementTypeFormatTraits::BufferSize( item );
                    }
                    return result;
                }
            }

            template<typename Writer>
            static constexpr void Write( Writer& writer, const T& object )
            {
                using ElementTypeFormatTraits = FormatTraits<ElementType>;
                for ( UInt64 i = 0; i < Count; ++i )
                {
                    ElementTypeFormatTraits::Write( writer, object[i] );
                }
            }
            template<typename Reader>
            static constexpr void Read( Reader& reader, T& object )
            {
                using ElementTypeFormatTraits = FormatTraits<ElementType>;
                for ( UInt64 i = 0; i < Count; ++i )
                {
                    ElementTypeFormatTraits::Read( reader, object[i] );
                }
            }
        };

        template<typename T, typename RT>
        struct VectorContainerFormatTraits : ContainerFormatTraitsBase<T, RT>
        {
            using Base = ContainerFormatTraitsBase<T, RT>;
            using Base::TypeTraits;

        private:
            using ElementType = typename TypeTraits::ElementType;
            using ElementTypeTraits = Types::TypeTraits<ElementType>;

            static constexpr size_t Count = TypeTraits::Count;

            static constexpr auto EvalTypeId( )
            {
                if constexpr ( ElementTypeTraits::IsBasic )
                {
                    return ElementTypeTraits::TypeId;
                }
                else
                {
                    return TypeTraits::TypeId;
                }
            }
            static constexpr auto TypeId = EvalTypeId( );

            static constexpr auto EvalFormat( )
            {
                if constexpr ( ElementTypeTraits::IsBasic )
                {
                    return MakeTuple( TypeId, ModifierFlags::Array );
                }
                else
                {
                    auto elementDescriptor = FormatTraits<ElementType>::Descriptor;
                    return MakeTuple( TypeId, ModifierFlags::Array, elementDescriptor );
                }
            }
        public:
            static constexpr auto Format = EvalFormat( );
            using FormatType = decltype( Format );

            static constexpr auto Descriptor = TupleCat( MakeTuple( SevenBitEncodedValue<sizeof( FormatType )>::value, static_cast<Byte>( '\x1' ) ), Format );
            using DescriptorType = decltype( Descriptor );


            static constexpr size_t BufferSize( const T& object ) noexcept
            {
                if constexpr ( Types::IsFixedSize<ElementType>::value )
                {
                    size_t dataSize = object.size() * Types::PackedSizeOf<T>::value;
                    size_t result = Core::SizeOf7BitEncodedValue( dataSize ) + dataSize;
                    return result;
                }
                else
                {
                    using ElementTypeFormatTraits = FormatTraits<ElementType>;

                    size_t count = object.size( );
                    size_t dataSize = 0;
                    for ( size_t i = 0; i < count; ++i )
                    {
                        const auto& item = object[i];
                        dataSize += ElementTypeFormatTraits::BufferSize( item );
                    }

                    size_t result = Core::SizeOf7BitEncodedValue( dataSize ) + dataSize;
                    return result;
                }
            }

            template<typename Writer>
            static constexpr void Write( Writer& writer, const T& object )
            {
                using ElementTypeFormatTraits = FormatTraits<ElementType>;

                size_t count = object.size( );
                writer.Write7BitEncoded( count );

                for ( UInt64 i = 0; i < count; ++i )
                {
                    ElementTypeFormatTraits::Write( writer, object[i] );
                }
            }
            template<typename Reader>
            static constexpr void Read( Reader& reader, T& object )
            {
                size_t count = reader.Read7BitEncoded( );
                object.reserve( count );

                using ElementTypeFormatTraits = FormatTraits<ElementType>;
                for ( UInt64 i = 0; i < count; ++i )
                {
                    ElementTypeFormatTraits::Read( reader, object.emplace_back( ) );
                }
            }
        };

        template<typename T, typename RT>
        struct StringContainerFormatTraits : ContainerFormatTraitsBase<T, RT>
        {
            using Base = ContainerFormatTraitsBase<T, RT>;
            using Base::TypeTraits;
            using ElementType = typename TypeTraits::ElementType;

            using ElementTypeTraits = Types::TypeTraits<ElementType>;
            static constexpr Types::BasicTypeId TypeId = ElementTypeTraits::TypeId;

            static constexpr auto Format = MakeTuple( TypeId, ModifierFlags::Array );
            using FormatType = decltype( Format );

            static constexpr auto Descriptor = TupleCat( MakeTuple( SevenBitEncodedValue<sizeof( FormatType )>::value, static_cast<Byte>( '\x1' ) ), Format );
            using DescriptorType = decltype( Descriptor );

            static constexpr size_t BufferSize( const T& object ) noexcept
            {
                size_t dataSize = object.size( );
                size_t result = Core::SizeOf7BitEncodedValue( dataSize ) + dataSize;
                return result;
            }

            template<typename Writer>
            static constexpr void Write( Writer& writer, const T& object )
            {
                using ElementTypeFormatTraits = FormatTraits<ElementType>;

                size_t count = object.size( );
                writer.Write7BitEncoded( count );
                writer.Write( object.data(), count * sizeof( TypeTraits::ElementType ) );
            }
            template<typename Reader>
            static constexpr void Read( Reader& reader, T& object )
            {
                size_t count = reader.Read7BitEncoded( );
                object.resize( count );
                reader.Read( object.data(), count * sizeof( TypeTraits::ElementType ) );
            }
        };





        template<typename T, typename RT>
        struct ContainerFormatTraits 
            : std::conditional_t
              <
                IsArrayContainer<T>, ArrayContainerFormatTraits<std::remove_cvref_t<T>, T>, 
                std::conditional_t
                <
                  IsVectorContainer<T>, VectorContainerFormatTraits<std::remove_cvref_t<T>, T>,
                    std::conditional_t
                    <
                      IsStdBasicString<T>, StringContainerFormatTraits<std::remove_cvref_t<T>, T>,
                      ContainerFormatTraitsBase<std::remove_cvref_t<T>, T>
                    >
                >
              >
        {
            
        };



        template<size_t N, typename T, typename ...Types>
        struct FormatTypeImplHelper
        {
            using TypeFormatTraits = FormatTraits<T>;
            static constexpr auto Format = TupleCat( TypeFormatTraits::Format, FormatTypeImplHelper<N-1, Types...>::Format );
            using FormatType = decltype( Format );
        };
        template<typename T, typename ...Types>
        struct FormatTypeImplHelper<1, T, Types...>
        {
            using TypeFormatTraits = FormatTraits<T>;
            using FormatType = TypeFormatTraits::FormatType;
            static constexpr FormatType Format = TypeFormatTraits::Format;
        };

        template<typename T, typename ...Types>
        struct FormatTypeImplHelper<0, T, Types...>
        {
            using FormatType = Tuple<>;
            static constexpr FormatType Format{};
        };

        template<typename T>
        struct FormatTypeImpl
        {
            static constexpr auto Format = FormatTraits<T>::Format;

        };
        template<typename ...Types>
        struct FormatTypeImpl<Tuple<Types...>>
        {
            static constexpr auto Format = FormatTypeImplHelper<sizeof...( Types ), Types...>::Format;
        };

        template<typename ...Types>
        struct FormatTypeImpl<std::tuple<Types...>>
        {
            static constexpr auto Format = FormatTypeImplHelper<sizeof...( Types ), Types...>::Format;
        };

        template<typename ...Types>
        struct FormatTypeImpl<std::pair<Types...>>
        {
            static constexpr auto Format = FormatTypeImplHelper<sizeof...( Types ), Types...>::Format;
        };


        template<typename ...Types>
        struct FormatTypeImpl<TypeList<Types...>>
        {
            static constexpr auto Format = FormatTypeImplHelper<sizeof...( Types ), Types...>::Format;
        };


        template<typename T, typename RT>
        struct TupleFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T, RT>;
        private:
            using Base::TypeTraits;
            static constexpr Types::TupleTypeId TypeId = TypeTraits::TypeId;

            using ImplType = FormatTypeImpl<std::remove_cvref_t<T>>;

            static constexpr auto HeaderByteSizeAndCount = MakeTuple( TypeId, 
                                                                        ModifierFlags::None, 
                                                                        SevenBitEncodedValue<sizeof( ImplType::Format )>::value, 
                                                                        SevenBitEncodedValue<TypeTraits::Count>::value );
        public:
            static constexpr auto Format = TupleCat( HeaderByteSizeAndCount, ImplType::Format );
            using FormatType = decltype( Format );
        private:
            static constexpr auto Sizes = MakeTuple( SevenBitEncodedValue<sizeof( FormatType )>::value, static_cast<Byte>( '\x1' ) );
        public:
            static constexpr auto Descriptor = TupleCat( Sizes, Format );
            using DescriptorType = decltype( Descriptor );


            static constexpr size_t BufferSize( const T& object ) noexcept
            {
                if constexpr ( TypeTraits::Count > 0 )
                {
                    if constexpr ( Types::IsFixedSize<T>::value )
                    {
                        return Types::PackedSizeOf<T>::value;
                    }
                    else
                    {
                        if constexpr ( IsStdTuple<T> || IsStdPair<T> )
                        {
                            size_t result = std::apply( []( auto&... v )
                            {
                                return ( FormatTraits<decltype( v )>::BufferSize( v ) + ... );
                            }, object );
                            return result;
                        }
                        else if constexpr ( IsCoreTuple<T> )
                        {
                            size_t result = Apply( []( auto&... v )
                            {
                                return ( FormatTraits<decltype( v )>::BufferSize( v ) + ... );
                            }, object );
                            return result;
                        }
                        else
                        {
                            static_assert( false, "Unknown tuple type" );
                        }
                    }
                }
                else
                {
                    return 0;
                }
            }

            template<typename Writer>
            static constexpr void Write( Writer& writer, const T& object )
            {
                if constexpr ( IsStdTuple<T> || IsStdPair<T> )
                {
                    std::apply( [&writer]( auto&... v )
                    {
                        ( FormatTraits<decltype( v )>::Write( writer, v ), ... );
                    }, object );
                }
                else if constexpr ( IsCoreTuple<T> )
                {
                    Apply( [&writer]( auto&... v )
                    {
                        ( FormatTraits<decltype( v )>::Write( writer, v ),  ... );
                    }, object );
                }
                else
                {
                    static_assert( false, "Unknown tuple type" );
                }
            }
            template<typename Reader>
            static constexpr void Read( Reader& reader, T& object )
            {
                if constexpr ( IsStdTuple<T> || IsStdPair<T> )
                {
                    std::apply( [&reader]( auto&... v )
                    {
                        ( FormatTraits<decltype( v )>::Read( reader, v ), ... );
                    }, object );
                }
                else if constexpr ( IsCoreTuple<T> )
                {
                    Apply( [&reader]( auto&... v )
                    {
                        ( FormatTraits<decltype( v )>::Read( reader, v ), ... );
                    }, object );
                }
                else
                {
                    static_assert( false, "Unknown tuple type" );
                }
            }
        };

        template<typename RT>
        struct TupleFormatTraits<Tuple<>, RT> : FormatTraitsBase<Tuple<>, RT>
        {
            using Base = FormatTraitsBase<Tuple<>, RT>;
            using Type = typename Base::Type;
        private:
            static constexpr Types::TupleTypeId TypeId = Types::TupleTypeId::Tuple;

            static constexpr auto HeaderByteSizeAndCount = MakeTuple( TypeId, ModifierFlags::None, static_cast<Byte>( '\x0' ), static_cast<Byte>( '\x0' ) );
        public:
            static constexpr auto Format = HeaderByteSizeAndCount;
            using FormatType = decltype( Format );
        private:
            static constexpr auto Sizes = MakeTuple( SevenBitEncodedValue<sizeof( FormatType )>::value, static_cast<Byte>( '\x1' ) );
        public:
            static constexpr auto Descriptor = TupleCat( Sizes, Format );
            using DescriptorType = decltype( Descriptor );

            static constexpr size_t BufferSize( const Type& object ) noexcept
            {
                return 0;
            }

            template<typename Writer>
            static constexpr void Write( Writer& writer, const Type& object )
            {

            }

            template<typename Reader>
            static constexpr void Read( Reader& reader, Type& object )
            {

            }
        };

        template<typename RT>
        struct TupleFormatTraits<std::tuple<>, RT> : FormatTraitsBase<std::tuple<>, RT>
        {
            using Base = FormatTraitsBase<std::tuple<>, RT>;
            using Type = typename Base::Type;
        private:
            static constexpr Types::TupleTypeId TypeId = Types::TupleTypeId::StdTuple;

            static constexpr auto HeaderByteSizeAndCount = MakeTuple( TypeId, ModifierFlags::None, static_cast<Byte>( '\x0' ), static_cast<Byte>( '\x0' ) );
        public:
            static constexpr auto Format = HeaderByteSizeAndCount;
            using FormatType = decltype( Format );
        private:
            static constexpr auto Sizes = MakeTuple( SevenBitEncodedValue<sizeof( FormatType )>::value, static_cast<Byte>( '\x1' ) );
        public:
            static constexpr auto Descriptor = TupleCat( Sizes, Format );
            using DescriptorType = decltype( Descriptor );

            static constexpr size_t BufferSize( const Type& object ) noexcept
            {
                return 0;
            }

            template<typename Writer>
            static constexpr void Write( Writer& writer, const Type& object )
            {

            }

            template<typename Reader>
            static constexpr void Read( Reader& reader, Type& object )
            {

            }
        };



        template<typename T, typename RT>
        struct OptionalFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T, RT>;
        };

        template<typename T, typename RT>
        struct UniquePtrFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T, RT>;
        };

        template<typename T, typename RT>
        struct SharedPtrFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T, RT>;
        };

        template<typename T, typename RT>
        struct VariantFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T, RT>;
        };

        template<typename T, typename RT>
        struct TypeListFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T, RT>;

        private:
            using Base::TypeTraits;
            static constexpr auto TypeId = TypeTraits::TypeId;

            using ImplType = FormatTypeImpl<std::remove_cvref_t<T>>;

            static constexpr auto HeaderByteSizeAndCount = MakeTuple( TypeId,
                                                                ModifierFlags::None,
                                                                SevenBitEncodedValue<sizeof( ImplType::Format )>::value,
                                                                SevenBitEncodedValue<TypeTraits::Count>::value );
        public:
            static constexpr auto Format = TupleCat( HeaderByteSizeAndCount, ImplType::Format );
            using FormatType = decltype( Format );
        private:
            static constexpr auto Sizes = MakeTuple( SevenBitEncodedValue<sizeof( FormatType )>::value, static_cast<Byte>( '\x1' ) );
        public:
            static constexpr auto Descriptor = TupleCat( Sizes, Format );
            using DescriptorType = decltype( Descriptor );

        };

        template<typename T, typename RT>
        struct AdaptedFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T, RT>;
            using Base::Type;
        private:
            using Base::TypeTraits;
            using TupleType = typename TypeTraits::TupleType;
            static constexpr auto TypeId = TypeTraits::TypeId;

            using ImplType = FormatTypeImpl<typename T::TypeList>;

            static constexpr auto HeaderByteSizeAndCount = MakeTuple( TypeId,
                                                                ModifierFlags::None,
                                                                SevenBitEncodedValue<sizeof( ImplType::Format )>::value,
                                                                SevenBitEncodedValue<TypeTraits::Count>::value );
        public:
            static constexpr auto Format = TupleCat( HeaderByteSizeAndCount, ImplType::Format );
            using FormatType = decltype( Format );
        private:
            static constexpr auto Sizes = MakeTuple( SevenBitEncodedValue<sizeof( FormatType )>::value, static_cast<Byte>( '\x1' ) );
        public:
            static constexpr auto Descriptor = TupleCat( Sizes, Format );
            using DescriptorType = decltype( Descriptor );
            
            static constexpr size_t BufferSize( const Type& object ) noexcept
            {
                if constexpr ( TypeTraits::Count > 0 )
                {
                    if constexpr ( Types::IsFixedSize<T>::value )
                    {
                        return Types::PackedSizeOf<T>::value;
                    }
                    else
                    {
                        size_t result = Apply( []( auto&... v )
                        {
                            return ( FormatTraits<decltype( v )>::BufferSize( v ) + ... );
                        }, reinterpret_cast<const TupleType&>(object) );
                        return result;
                    }
                }
                else
                {
                    return 0;
                }
            }

            template<typename Writer>
            static constexpr void Write( Writer& writer, const Type& object )
            {
                Apply( [&writer]( auto&... v )
                {
                    ( FormatTraits<decltype( v )>::Write( writer, v ), ... );
                }, reinterpret_cast<const TupleType&>( object ) );
            }
            template<typename Reader>
            static constexpr void Read( Reader& reader, T& object )
            {
                Apply( [&reader]( auto&... v )
                {
                    ( FormatTraits<decltype( v )>::Read( reader, v ), ... );
                }, reinterpret_cast<const TupleType&>( object ) );
            }
            

        };

    

        template<typename T, typename RT>
        struct ConstantFormatTraits : FormatTraitsBase<T, RT>
        {
            using Base = FormatTraitsBase<T, RT>;
        };



        template<typename T>
        struct FormatTraits :
            std::conditional_t
            <
              IsBasicType<T>, Persistent::Internal::BasicFormatTraits<std::remove_cvref_t<T>,T>,
              std::conditional_t
              <
                IsArray<T>, Persistent::Internal::ArrayFormatTraits<std::remove_cvref_t<T>, T>,
                std::conditional_t
                <  
                  IsPointer<T>, Persistent::Internal::PointerFormatTraits<std::remove_cvref_t<T>, T>,
                  std::conditional_t
                  <
                    IsContainer<T>, Persistent::Internal::ContainerFormatTraits<std::remove_cvref_t<T>, T>,
                    std::conditional_t
                    < 
                      IsTupleType<T>, Persistent::Internal::TupleFormatTraits<std::remove_cvref_t<T>, T>,
                      std::conditional_t
                      < 
                        IsStdOptional<T>, Persistent::Internal::OptionalFormatTraits<std::remove_cvref_t<T>, T>,
                        std::conditional_t
                        <
                          IsStdUniquePtr<T>, Persistent::Internal::UniquePtrFormatTraits<std::remove_cvref_t<T>, T>,
                          std::conditional_t
                          <
                            IsStdSharedPtr<T>, Persistent::Internal::SharedPtrFormatTraits<std::remove_cvref_t<T>, T>,
                            std::conditional_t
                            <
                              IsStdVariant<T>, Persistent::Internal::VariantFormatTraits<std::remove_cvref_t<T>, T>,
                              std::conditional_t
                              <
                                IsTypeList<T>, Persistent::Internal::TypeListFormatTraits<std::remove_cvref_t<T>, T>,
                                std::conditional_t
                                <
                                  IsConstant<T>, Persistent::Internal::ConstantFormatTraits<std::remove_cvref_t<T>, T>,
                                  std::conditional_t
                                  <
                                    Types::IsAdapted<T>, Persistent::Internal::AdaptedFormatTraits<std::remove_cvref_t<T>, T>,
                                    Persistent::Internal::UnsupportedFormatTraits<std::remove_cvref_t<T>, T> 
                                  >
                                >
                              >
                            >
                          >
                        >
                      >
                    >
                  >
                >
              > 
            >
        { };

    }

    template<typename T>
    class Constant
    {
        using RawType = T;
        using Type = std::remove_cvref_t<T>;

    };


    
    /// <summary>
    /// Computes a binary description of the arguments
    /// that can be used to decode the serialized data
    /// on the receiving end.
    /// </summary>
    template<typename ...Args>
    constexpr auto Descriptor( Args&& ... args )
    {
        if constexpr ( sizeof...( Args ) > 0 )
        {
            using Types = TypeList<Args...>;
            using FormatTraitsT = Internal::FormatTraits<Types>;
            return FormatTraitsT::Descriptor;
        }
        else
        {
            return MakeTuple( static_cast<Byte>( 4 ), static_cast<Byte>( 1 ), Types::UtilityTypeId::TypeList, ModifierFlags::None, static_cast<Byte>( 0 ), static_cast<Byte>( 0 ) );
        }
    }

    template<typename ...Types>
    struct DescriptorType
    {
    private:
        using FormatTraitsT = Internal::FormatTraits<TypeList<Types...>>;
    public:
        using type = typename FormatTraitsT::DescriptorType;
        static constexpr auto value = FormatTraitsT::Descriptor;
    };

    template<>
    struct DescriptorType<>
    {
        using type = Tuple<Byte, Byte, Types::UtilityTypeId, ModifierFlags, Byte, Byte>;
        static constexpr auto value = MakeTuple( static_cast<Byte>( 4 ), static_cast<Byte>( 1 ), Types::UtilityTypeId::TypeList, ModifierFlags::None, static_cast<Byte>( 0 ), static_cast<Byte>( 0 ) );
    };





    
    /// <summary>
    /// Returns true if the size of the buffer required to 
    /// serialize the arguments is independent of the contents
    /// of each argument.
    /// </summary>
    template<typename ...Args>
    inline constexpr bool IsFixedSize( const Args& ... args )
    {
        if constexpr ( sizeof...( Args ) > 0 )
        {
            return ( Types::IsFixedSize<Args>::value && ... );
        }
        else
        {
            return true;
        }
    }
    

    /// <summary>
    /// Calculates the size of the buffer required to serialize
    /// the data passed as arguments to the function.
    /// </summary>
    /// <remarks>
    /// if IsFixedSize( ... ) returns true for the set of arguments
    /// then none of the arguments varies in size between invocations
    /// and BufferSize( ... ) will allways return the same value
    /// </remarks>
    template<typename ...Args>
    inline constexpr size_t BufferSize( const Args& ... args )
    {
        if constexpr ( sizeof...( Args ) > 0 )
        {
            return ( Internal::FormatTraits<Args>::BufferSize( args ) + ... );
        }
        else
        {
            return 0;
        }
    }

    template<typename Writer, typename ...Args>
    inline constexpr void Write( Writer& writer, const Args& ... args )
    {
        if constexpr ( sizeof...( Args ) > 0 )
        {
            ( Internal::FormatTraits<Args>::Write( writer, args ), ... );
        }
    }

    template<typename Reader, typename ...Args>
    inline constexpr void Read( Reader& reader, Args& ... args )
    {
        if constexpr ( sizeof...( Args ) > 0 )
        {
            ( Internal::FormatTraits<Args>::Read( reader, args ), ... );
        }
    }

    
    inline bool IsBasicTypeDescriptor( const Byte* descriptor, size_t descriptorSize ) noexcept
    {
        if ( descriptorSize == 8 &&
            descriptor[0] == 6 &&
            descriptor[1] == 1 &&
            descriptor[2] == static_cast<Byte>( Types::UtilityTypeId::TypeList ) &&
            descriptor[3] == static_cast<Byte>( ModifierFlags::None ) &&
            descriptor[4] == 2 &&
            descriptor[5] == 1 &&
            descriptor[6] >= static_cast<Byte>( Types::BasicTypeIdMin ) &&
            descriptor[6] >= static_cast<Byte>( Types::BasicTypeIdMax ) &&
            ( (descriptor[7] & static_cast<Byte>( Persistent::ModifierFlags::Array | Persistent::ModifierFlags::Fixed | Persistent::ModifierFlags::Sequence )) == static_cast<Byte>( Persistent::ModifierFlags::None ) ) )
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    template<typename T>
        requires ((IsStdVector<T> || IsCoreVector<T> || IsStdSpan<T>) && std::is_same_v<Byte, typename std::remove_cvref_t<T>::value_type >)
    inline bool IsBasicTypeDescriptor(const T& bytes )
    {
        return IsBasicTypeDescriptor( bytes.data(), bytes.size() );
    }


    inline bool IsIntegerBasicTypeDescriptor( const Byte* descriptor, size_t descriptorSize ) noexcept
    {
        if ( descriptorSize == 8 &&
            descriptor[0] == 6 &&
            descriptor[1] == 1 &&
            descriptor[2] == static_cast<Byte>( Types::UtilityTypeId::TypeList ) &&
            descriptor[3] == static_cast<Byte>( ModifierFlags::None ) &&
            descriptor[4] == 2 &&
            descriptor[5] == 1 &&
            ( (descriptor[7] & static_cast<Byte>( Persistent::ModifierFlags::Array | Persistent::ModifierFlags::Fixed | Persistent::ModifierFlags::Sequence )) == static_cast<Byte>( Persistent::ModifierFlags::None ) ) )
        {
            auto typeId = static_cast<Types::BasicTypeId>( descriptor[6] );
            switch ( typeId )
            {
                case Types::BasicTypeId::Unknown:
                case Types::BasicTypeId::Boolean:
                case Types::BasicTypeId::Char:
                case Types::BasicTypeId::WChar:
                case Types::BasicTypeId::Single:
                case Types::BasicTypeId::Double:
                    return false;
            }
            return true;
        }
        else
        {
            return false;
        }
    }

    template<typename T>
        requires ( ( IsStdVector<T> || IsCoreVector<T> || IsStdSpan<T> ) && std::is_same_v<Byte, typename std::remove_cvref_t<T>::value_type > )
    inline bool IsIntegerBasicTypeDescriptor( const T& bytes )
    {
        return IsIntegerBasicTypeDescriptor( bytes.data( ), bytes.size( ) );
    }

}

#pragma pack(pop)
#endif


After posting the message, the C++ code doesn't look all that bad, even if some of the template stuff could do with a bit more coloring.

I pasted the code 'as-is', and it is actually readable on the site Thumbs Up | :thumbsup: . If I remember correctly this used to be a big 'no-no' some years ago, and everything had to be encoded as HTML.

Quote:
Ugh. The apostrophe separated numbers are just...ugh.

They have, as you know, been a part of C++ for some time now, and they makes big numbers more readable: 1000000000000 vs 1'000'000'000'000 - while 1'0 is just silly compared to 10

Have a nice weekend Smile | :)
Espen Harlinn
Senior Architect - Ulriken Consulting AS

The competent programmer is fully aware of the strictly limited size of his own skull; therefore he approaches the programming task in full humility, and among other things he avoids clever tricks like the plague.Edsger W.Dijkstra


modified 26-Jun-21 5:08am.

GeneralRe: C++ code formatting problems Pin
Nelek26-Jun-21 1:09
protectorNelek26-Jun-21 1:09 
GeneralRe: C++ code formatting problems Pin
Espen Harlinn26-Jun-21 1:28
professionalEspen Harlinn26-Jun-21 1:28 
JokeRe: C++ code formatting problems Pin
Nelek26-Jun-21 3:18
protectorNelek26-Jun-21 3:18 
GeneralRe: C++ code formatting problems Pin
Nelek25-Jun-21 8:20
protectorNelek25-Jun-21 8:20 
GeneralRe: C++ code formatting problems Pin
Espen Harlinn25-Jun-21 12:06
professionalEspen Harlinn25-Jun-21 12:06 
SuggestionIn Q&A, TextBox messing user input. Pin
Patrice T17-Jun-21 10:38
mvePatrice T17-Jun-21 10:38 
GeneralRe: In Q&A, TextBox messing user input. Pin
Greg Utas17-Jun-21 11:55
professionalGreg Utas17-Jun-21 11:55 
GeneralRe: In Q&A, TextBox messing user input. Pin
Patrice T17-Jun-21 12:00
mvePatrice T17-Jun-21 12:00 
GeneralRe: In Q&A, TextBox messing user input. Pin
Matthew Dennis21-Jun-21 4:55
sysadminMatthew Dennis21-Jun-21 4:55 
GeneralRe: In Q&A, TextBox messing user input. Pin
Patrice T21-Jun-21 18:27
mvePatrice T21-Jun-21 18:27 
GeneralRe: In Q&A, TextBox messing user input. Pin
Chris Maunder22-Jun-21 7:50
cofounderChris Maunder22-Jun-21 7:50 
GeneralRe: In Q&A, TextBox messing user input. Pin
Patrice T22-Jun-21 8:38
mvePatrice T22-Jun-21 8:38 
GeneralRe: In Q&A, TextBox messing user input. Pin
Patrice T30-Jun-21 9:29
mvePatrice T30-Jun-21 9:29 
SuggestionJust a thought about article downloads. Pin
OriginalGriff16-Jun-21 20:10
mveOriginalGriff16-Jun-21 20:10 
SuggestionLost all my work Pin
CodeErgoSum14-Jun-21 20:55
CodeErgoSum14-Jun-21 20:55 
GeneralRe: Lost all my work Pin
CodeErgoSum14-Jun-21 21:02
CodeErgoSum14-Jun-21 21:02 
GeneralRe: Lost all my work Pin
CodeErgoSum14-Jun-21 21:20
CodeErgoSum14-Jun-21 21:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Flags: SolvedFixed

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.