#include "FastNoise/FastNoiseMetadata.h" #include "Base64.h" #include #include #include #include using namespace FastNoise; std::vector Metadata::sMetadataClasses; NodeData::NodeData( const Metadata* data ) { metadata = data; if( metadata ) { for( const auto& value : metadata->memberVariables ) { variables.push_back( value.valueDefault ); } for( const auto& value : metadata->memberNodes ) { (void)value; nodes.push_back( nullptr ); } for( const auto& value : metadata->memberHybrids ) { hybrids.emplace_back( nullptr, value.valueDefault ); } } } template void AddToDataStream( std::vector& dataStream, T value ) { for( size_t i = 0; i < sizeof( T ); i++ ) { dataStream.push_back( (uint8_t)(value >> (i * 8)) ); } } bool SerialiseNodeDataInternal( NodeData* nodeData, bool fixUp, std::vector& dataStream, std::unordered_map& referenceIds, std::unordered_set dependancies = {} ) { const Metadata* metadata = nodeData->metadata; if( !metadata || nodeData->variables.size() != metadata->memberVariables.size() || nodeData->nodes.size() != metadata->memberNodes.size() || nodeData->hybrids.size() != metadata->memberHybrids.size() ) { assert( 0 ); // Member size mismatch with metadata return false; } if( fixUp ) { dependancies.insert( nodeData ); for( auto& node : nodeData->nodes ) { if( dependancies.find( node ) != dependancies.end() ) { node = nullptr; } } for( auto& hybrid : nodeData->hybrids ) { if( dependancies.find( hybrid.first ) != dependancies.end() ) { hybrid.first = nullptr; } } } auto reference = referenceIds.find( nodeData ); if( reference != referenceIds.end() ) { AddToDataStream( dataStream, UINT16_MAX ); AddToDataStream( dataStream, reference->second ); return true; } AddToDataStream( dataStream, metadata->id ); for( size_t i = 0; i < metadata->memberVariables.size(); i++ ) { AddToDataStream( dataStream, nodeData->variables[i].i ); } for( size_t i = 0; i < metadata->memberNodes.size(); i++ ) { if( fixUp && nodeData->nodes[i] ) { std::unique_ptr gen( metadata->NodeFactory() ); SmartNode<> node( nodeData->nodes[i]->metadata->NodeFactory() ); if( !metadata->memberNodes[i].setFunc( gen.get(), node ) ) { nodeData->nodes[i] = nullptr; return false; } } if( !nodeData->nodes[i] || !SerialiseNodeDataInternal( nodeData->nodes[i], fixUp, dataStream, referenceIds, dependancies ) ) { return false; } } for( size_t i = 0; i < metadata->memberHybrids.size(); i++ ) { if( !nodeData->hybrids[i].first ) { AddToDataStream( dataStream, (uint8_t)0 ); Metadata::MemberVariable::ValueUnion v = nodeData->hybrids[i].second; AddToDataStream( dataStream, v.i ); } else { if( fixUp ) { std::unique_ptr gen( metadata->NodeFactory() ); std::shared_ptr node( nodeData->hybrids[i].first->metadata->NodeFactory() ); if( !metadata->memberHybrids[i].setNodeFunc( gen.get(), node ) ) { nodeData->hybrids[i].first = nullptr; return false; } } AddToDataStream( dataStream, (uint8_t)1 ); if( !SerialiseNodeDataInternal( nodeData->hybrids[i].first, fixUp, dataStream, referenceIds, dependancies ) ) { return false; } } } referenceIds.emplace( nodeData, (uint16_t)referenceIds.size() ); return true; } std::string Metadata::SerialiseNodeData( NodeData* nodeData, bool fixUp ) { std::vector serialData; std::unordered_map referenceIds; if( !SerialiseNodeDataInternal( nodeData, fixUp, serialData, referenceIds ) ) { return ""; } return Base64::Encode( serialData ); } template bool GetFromDataStream( const std::vector& dataStream, size_t& idx, T& value ) { if( dataStream.size() < idx + sizeof( T ) ) { return false; } value = *reinterpret_cast( dataStream.data() + idx ); idx += sizeof( T ); return true; } SmartNode<> DeserialiseSmartNodeInternal( const std::vector& serialisedNodeData, size_t& serialIdx, std::unordered_map>& referenceNodes, FastSIMD::eLevel level = FastSIMD::Level_Null ) { uint16_t nodeId; if( !GetFromDataStream( serialisedNodeData, serialIdx, nodeId ) ) { return nullptr; } if( nodeId == UINT16_MAX ) { uint16_t referenceId; if( !GetFromDataStream( serialisedNodeData, serialIdx, referenceId ) ) { return nullptr; } auto refNode = referenceNodes.find( referenceId ); if( refNode == referenceNodes.end() ) { return nullptr; } return refNode->second; } const Metadata* metadata = Metadata::GetMetadataClass( nodeId ); if( !metadata ) { return nullptr; } SmartNode<> generator( metadata->NodeFactory( level ) ); for( const auto& var : metadata->memberVariables ) { Metadata::MemberVariable::ValueUnion v; if( !GetFromDataStream( serialisedNodeData, serialIdx, v ) ) { return nullptr; } var.setFunc( generator.get(), v ); } for( const auto& node : metadata->memberNodes ) { SmartNode<> nodeGen = DeserialiseSmartNodeInternal( serialisedNodeData, serialIdx, referenceNodes, level ); if( !nodeGen || !node.setFunc( generator.get(), nodeGen ) ) { return nullptr; } } for( const auto& hybrid : metadata->memberHybrids ) { uint8_t isGenerator; if( !GetFromDataStream( serialisedNodeData, serialIdx, isGenerator ) || isGenerator > 1 ) { return nullptr; } if( isGenerator ) { SmartNode<> nodeGen = DeserialiseSmartNodeInternal( serialisedNodeData, serialIdx, referenceNodes, level ); if( !nodeGen || !hybrid.setNodeFunc( generator.get(), nodeGen ) ) { return nullptr; } } else { float v; if( !GetFromDataStream( serialisedNodeData, serialIdx, v ) ) { return nullptr; } hybrid.setValueFunc( generator.get(), v ); } } referenceNodes.emplace( (uint16_t)referenceNodes.size(), generator ); return generator; } SmartNode<> Metadata::DeserialiseSmartNode( const char* serialisedBase64NodeData, FastSIMD::eLevel level ) { std::vector dataStream = Base64::Decode( serialisedBase64NodeData ); size_t startIdx = 0; std::unordered_map> referenceNodes; return DeserialiseSmartNodeInternal( dataStream, startIdx, referenceNodes, level ); } NodeData* DeserialiseNodeDataInternal( const std::vector& serialisedNodeData, std::vector>& nodeDataOut, size_t& serialIdx, std::unordered_map& referenceNodes ) { uint16_t nodeId; if( !GetFromDataStream( serialisedNodeData, serialIdx, nodeId ) ) { return nullptr; } if( nodeId == UINT16_MAX ) { uint16_t referenceId; if( !GetFromDataStream( serialisedNodeData, serialIdx, referenceId ) ) { return nullptr; } auto refNode = referenceNodes.find( referenceId ); if( refNode == referenceNodes.end() ) { return nullptr; } return refNode->second; } const Metadata* metadata = Metadata::GetMetadataClass( nodeId ); if( !metadata ) { return nullptr; } std::unique_ptr nodeData( new NodeData( metadata ) ); for( auto& var : nodeData->variables ) { if( !GetFromDataStream( serialisedNodeData, serialIdx, var ) ) { return nullptr; } } for( auto& node : nodeData->nodes ) { node = DeserialiseNodeDataInternal( serialisedNodeData, nodeDataOut, serialIdx, referenceNodes ); if( !node ) { return nullptr; } } for( auto& hybrid : nodeData->hybrids ) { uint8_t isGenerator; if( !GetFromDataStream( serialisedNodeData, serialIdx, isGenerator ) || isGenerator > 1 ) { return nullptr; } if( isGenerator ) { hybrid.first = DeserialiseNodeDataInternal( serialisedNodeData, nodeDataOut, serialIdx, referenceNodes ); if( !hybrid.first ) { return nullptr; } } else { if( !GetFromDataStream( serialisedNodeData, serialIdx, hybrid.second ) ) { return nullptr; } } } referenceNodes.emplace( (uint16_t)referenceNodes.size(), nodeData.get() ); return nodeDataOut.emplace_back( std::move( nodeData ) ).get(); } NodeData* Metadata::DeserialiseNodeData( const char* serialisedBase64NodeData, std::vector>& nodeDataOut ) { std::vector dataStream = Base64::Decode( serialisedBase64NodeData ); size_t startIdx = 0; std::unordered_map referenceNodes; return DeserialiseNodeDataInternal( dataStream, nodeDataOut, startIdx, referenceNodes ); } #define FASTSIMD_BUILD_CLASS2( CLASS ) \ const CLASS::Metadata g ## CLASS ## Metadata( #CLASS );\ const FastNoise::Metadata* CLASS::GetMetadata() const\ {\ return &g ## CLASS ## Metadata;\ }\ Generator* CLASS::Metadata::NodeFactory( FastSIMD::eLevel l ) const\ {\ return FastSIMD::New( l );\ } #define FASTSIMD_BUILD_CLASS( CLASS ) FASTSIMD_BUILD_CLASS2( CLASS ) #define FASTNOISE_CLASS( CLASS ) CLASS #define FASTSIMD_INCLUDE_HEADER_ONLY #include "FastNoise/FastNoise_BuildList.inl"