162 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <asset_parser/assets/text.hpp>
 | |
| 
 | |
| namespace Assets {
 | |
| 
 | |
| /* static */ void TextAsset::pack(const PackageData &data, const std::filesystem::path &out_path)
 | |
| {
 | |
| 	const auto &[metadata, text_metadata, text] = data;
 | |
| 
 | |
| 	auto stream = std::ofstream { out_path, std::ios::binary | std::ios::trunc };
 | |
| 	if (!stream.is_open())
 | |
| 	{
 | |
| 		throw std::runtime_error {
 | |
| 			std::format("Failed to open ofstream for packing Text at: {}", out_path.string())
 | |
| 		};
 | |
| 	}
 | |
| 	stream.seekp(0);
 | |
| 
 | |
| 	// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
 | |
| 	stream.write((char *)¤t_version, sizeof(current_version));
 | |
| 	stream.write((char *)&metadata, sizeof(metadata));
 | |
| 	stream.write((char *)&text_metadata, sizeof(text_metadata));
 | |
| 
 | |
| 	constexpr auto number_of_blobs = uint32_t { 1 };
 | |
| 	stream.write((char *)&number_of_blobs, sizeof(number_of_blobs));
 | |
| 
 | |
| 	auto textblob_metadata = BlobMetadata {
 | |
| 		.tag = BlobMetadata::Tag::text,
 | |
| 		.offset = static_cast<size_t>(stream.tellp()) + sizeof(BlobMetadata),
 | |
| 		.compression_type = CompressionType::None,
 | |
| 		.compressed_size = text.size(),
 | |
| 		.uncompressed_size = text.size(),
 | |
| 	};
 | |
| 
 | |
| 	stream.write((char *)&textblob_metadata, sizeof(textblob_metadata));
 | |
| 	stream.write((char *)text.data(), static_cast<long>(text.size()));
 | |
| 	// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
 | |
| }
 | |
| 
 | |
| TextAsset::TextAsset(const std::filesystem::path &path)
 | |
| {
 | |
| 	m_stream = std::ifstream { path, std::ios::binary };
 | |
| 	if (!m_stream.is_open())
 | |
| 	{
 | |
| 		throw std::runtime_error {
 | |
| 			std::format("Failed to open ifstream for loading Text asset at: {}", path.string())
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
 | |
| 	m_stream.read((char *)&version, sizeof(version));
 | |
| 	m_stream.read((char *)&m_asset_metadata, sizeof(m_asset_metadata));
 | |
| 	m_stream.read((char *)&m_metadata, sizeof(m_metadata));
 | |
| 
 | |
| 	auto num_blobs = uint32_t {};
 | |
| 	m_stream.read((char *)&num_blobs, sizeof(num_blobs));
 | |
| 	if (num_blobs != 1)
 | |
| 	{
 | |
| 		throw std::runtime_error {
 | |
| 			std::format("Failed to load Text asset: invalid number of blobs: {}", num_blobs)
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	m_stream.read((char *)&m_text_blob_metadata, sizeof(m_text_blob_metadata));
 | |
| 	if (m_text_blob_metadata.tag != BlobMetadata::Tag::text)
 | |
| 	{
 | |
| 		throw std::runtime_error {
 | |
| 			std::format(
 | |
| 			    "Failed to load Text asset: invalid blob tag, expected {}, got {}",
 | |
| 			    std::to_underlying(BlobMetadata::Tag::text),
 | |
| 			    std::to_underlying(m_text_blob_metadata.tag)
 | |
| 			),
 | |
| 		};
 | |
| 	}
 | |
| 	// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
 | |
| }
 | |
| 
 | |
| void TextAsset::unpack_blob(
 | |
|     BlobMetadata::Tag tag,
 | |
|     std::byte *destination,
 | |
|     size_t destination_capacity
 | |
| ) const
 | |
| {
 | |
| 	if (tag != BlobMetadata::Tag::text)
 | |
| 	{
 | |
| 		throw std::runtime_error {
 | |
| 			std::format("Invalid tag for unpack_blob of TextAsset: {}", std::to_underlying(tag))
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	m_stream.seekg(static_cast<long>(m_text_blob_metadata.offset));
 | |
| 	switch (m_text_blob_metadata.compression_type)
 | |
| 	{
 | |
| 	case Assets::CompressionType::None:
 | |
| 		if (m_text_blob_metadata.uncompressed_size != m_text_blob_metadata.compressed_size)
 | |
| 		{
 | |
| 			throw std::runtime_error(
 | |
| 			    "Failed to unpack blob from TextAsset: "
 | |
| 			    "compressed/uncompressed size mismatch for no compression "
 | |
| 			    "type"
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		if (m_text_blob_metadata.uncompressed_size > destination_capacity)
 | |
| 		{
 | |
| 			throw std::runtime_error(
 | |
| 			    "Failed to unpack blob from TextAsset: "
 | |
| 			    "uncompressed_size > destination_capacity, unpacking "
 | |
| 			    "would result in segfault"
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		if (!m_stream.is_open())
 | |
| 		{
 | |
| 			throw std::runtime_error(
 | |
| 			    "Failed to unpack blob from TextAsset: ifstream is "
 | |
| 			    "closed"
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		m_stream.read(
 | |
| 		    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
 | |
| 		    (char *)destination,
 | |
| 		    static_cast<long>(m_text_blob_metadata.uncompressed_size)
 | |
| 		);
 | |
| 
 | |
| 		return;
 | |
| 
 | |
| 	default:
 | |
| 		throw std::runtime_error(
 | |
| 		    std::format(
 | |
| 		        "Failed to unpack blob from TextAsset: unsupported "
 | |
| 		        "compression type: {}",
 | |
| 		        std::to_underlying(m_text_blob_metadata.compression_type)
 | |
| 		    )
 | |
| 		);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| [[nodiscard]] auto TextAsset::get_asset_metadata() const -> const Asset::Metadata &
 | |
| {
 | |
| 	return m_asset_metadata;
 | |
| }
 | |
| 
 | |
| [[nodiscard]] auto TextAsset::get_metadata() const -> const Metadata &
 | |
| {
 | |
| 	return m_metadata;
 | |
| }
 | |
| 
 | |
| [[nodiscard]] auto TextAsset::get_blob_metadata(BlobMetadata::Tag tag) const -> const BlobMetadata &
 | |
| {
 | |
| 	if (tag != BlobMetadata::Tag::text)
 | |
| 	{
 | |
| 		throw std::runtime_error { std::format(
 | |
| 			"Invalid tag for get_blob_metadata of TextAsset: {}",
 | |
| 			std::to_underlying(tag)
 | |
| 		) };
 | |
| 	}
 | |
| 
 | |
| 	return m_text_blob_metadata;
 | |
| }
 | |
| 
 | |
| } // namespace Assets
 |