Przeglądaj źródła

Always use std::vector<uint8_t> to store binary map

Ivan Savenko 2 lat temu
rodzic
commit
4a5c1556a1

+ 12 - 16
lib/campaign/CampaignHandler.cpp

@@ -85,30 +85,25 @@ std::shared_ptr<CampaignState> CampaignHandler::getCampaign( const std::string &
 	std::vector<std::vector<ui8>> files = getFile(std::move(fileStream), false);
 
 	readCampaign(ret.get(), files[0], resourceID.getName(), modName, encoding);
-	
+
 	//first entry is campaign header. start loop from 1
-	for(int scenarioID = 0, g = 1; g < files.size() && scenarioID < ret->numberOfScenarios; ++g)
+	for(int scenarioIndex = 0, fileIndex = 1; fileIndex < files.size() && scenarioIndex < ret->numberOfScenarios; scenarioIndex++)
 	{
-		auto id = static_cast<CampaignScenarioID>(scenarioID);
+		auto scenarioID = static_cast<CampaignScenarioID>(scenarioIndex);
 
-		while(!ret->scenarios[id].isNotVoid()) //skip void scenarios
-			scenarioID++;
+		if(!ret->scenarios[scenarioID].isNotVoid()) //skip void scenarios
+			continue;
 
 		std::string scenarioName = resourceID.getName();
 		boost::to_lower(scenarioName);
-		scenarioName += ':' + std::to_string(g - 1);
+		scenarioName += ':' + std::to_string(fileIndex - 1);
 
 		//set map piece appropriately, convert vector to string
-		ret->mapPieces[id].assign(reinterpret_cast<const char*>(files[g].data()), files[g].size());
-		CMapService mapService;
-		auto hdr = mapService.loadMapHeader(
-			reinterpret_cast<const ui8 *>(ret->mapPieces[id].c_str()),
-			static_cast<int>(ret->mapPieces[id].size()),
-			scenarioName,
-			modName,
-			encoding);
-		ret->scenarios[id].scenarioName = hdr->name;
-		scenarioID++;
+		ret->mapPieces[scenarioID] = files[fileIndex];
+
+		auto hdr = ret->getMapHeader(scenarioID);
+		ret->scenarios[scenarioID].scenarioName = hdr->name;
+		fileIndex++;
 	}
 
 	return ret;
@@ -585,6 +580,7 @@ std::vector< std::vector<ui8> > CampaignHandler::getFile(std::unique_ptr<CInputS
 		std::vector<ui8> block(stream.getSize());
 		stream.read(block.data(), block.size());
 		ret.push_back(block);
+		ret.back().shrink_to_fit();
 	}
 	while (!headerOnly && stream.getNextBlock());
 

+ 4 - 6
lib/campaign/CampaignState.cpp

@@ -307,9 +307,8 @@ std::unique_ptr<CMap> CampaignState::getMap(CampaignScenarioID scenarioId) const
 	std::string scenarioName = filename.substr(0, filename.find('.'));
 	boost::to_lower(scenarioName);
 	scenarioName += ':' + std::to_string(static_cast<int>(scenarioId));
-	const std::string & mapContent = mapPieces.find(scenarioId)->second;
-	const auto * buffer = reinterpret_cast<const ui8 *>(mapContent.data());
-	return mapService.loadMap(buffer, static_cast<int>(mapContent.size()), scenarioName, modName, encoding);
+	const auto & mapContent = mapPieces.find(scenarioId)->second;
+	return mapService.loadMap(mapContent.data(), mapContent.size(), scenarioName, modName, encoding);
 }
 
 std::unique_ptr<CMapHeader> CampaignState::getMapHeader(CampaignScenarioID scenarioId) const
@@ -321,9 +320,8 @@ std::unique_ptr<CMapHeader> CampaignState::getMapHeader(CampaignScenarioID scena
 	std::string scenarioName = filename.substr(0, filename.find('.'));
 	boost::to_lower(scenarioName);
 	scenarioName += ':' + std::to_string(static_cast<int>(scenarioId));
-	const std::string & mapContent = mapPieces.find(scenarioId)->second;
-	const auto * buffer = reinterpret_cast<const ui8 *>(mapContent.data());
-	return mapService.loadMapHeader(buffer, static_cast<int>(mapContent.size()), scenarioName, modName, encoding);
+	const auto & mapContent = mapPieces.find(scenarioId)->second;
+	return mapService.loadMapHeader(mapContent.data(), mapContent.size(), scenarioName, modName, encoding);
 }
 
 std::shared_ptr<CMapInfo> CampaignState::getMapInfo(CampaignScenarioID scenarioId) const

+ 1 - 1
lib/campaign/CampaignState.h

@@ -230,7 +230,7 @@ class DLL_LINKAGE CampaignState : public Campaign
 	/// List of all maps completed by player, in order of their completion
 	std::vector<CampaignScenarioID> mapsConquered;
 
-	std::map<CampaignScenarioID, std::string > mapPieces; //binary h3ms, scenario number -> map data
+	std::map<CampaignScenarioID, std::vector<uint8_t> > mapPieces; //binary h3ms, scenario number -> map data
 	std::map<CampaignScenarioID, ui8> chosenCampaignBonuses;
 	std::optional<CampaignScenarioID> currentMap;
 

+ 3 - 3
lib/mapping/CMapService.cpp

@@ -48,7 +48,7 @@ std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ResourceID & name)
 	return getMapLoader(stream, name.getName(), modName, encoding)->loadMapHeader();
 }
 
-std::unique_ptr<CMap> CMapService::loadMap(const ui8 * buffer, int size, const std::string & name,  const std::string & modName, const std::string & encoding) const
+std::unique_ptr<CMap> CMapService::loadMap(const uint8_t * buffer, int size, const std::string & name,  const std::string & modName, const std::string & encoding) const
 {
 	auto stream = getStreamFromMem(buffer, size);
 	std::unique_ptr<CMap> map(getMapLoader(stream, name, modName, encoding)->loadMap());
@@ -61,7 +61,7 @@ std::unique_ptr<CMap> CMapService::loadMap(const ui8 * buffer, int size, const s
 	return map;
 }
 
-std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const
+std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const
 {
 	auto stream = getStreamFromMem(buffer, size);
 	std::unique_ptr<CMapHeader> header = getMapLoader(stream, name, modName, encoding)->loadMapHeader();
@@ -111,7 +111,7 @@ std::unique_ptr<CInputStream> CMapService::getStreamFromFS(const ResourceID & na
 	return CResourceHandler::get()->load(name);
 }
 
-std::unique_ptr<CInputStream> CMapService::getStreamFromMem(const ui8 * buffer, int size)
+std::unique_ptr<CInputStream> CMapService::getStreamFromMem(const uint8_t * buffer, int size)
 {
 	return std::unique_ptr<CInputStream>(new CMemoryStream(buffer, size));
 }

+ 5 - 5
lib/mapping/CMapService.h

@@ -56,7 +56,7 @@ public:
 	 * @param name indicates name of file that will be used during map header patching
 	 * @return a unique ptr to the loaded map class
 	 */
-	virtual std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const = 0;
+	virtual std::unique_ptr<CMap> loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const = 0;
 
 	/**
 	 * Loads the VCMI/H3 map header from a buffer. This method is temporarily
@@ -65,7 +65,7 @@ public:
 	 * @param name indicates name of file that will be used during map header patching
 	 * @return a unique ptr to the loaded map class
 	 */
-	virtual std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const = 0;
+	virtual std::unique_ptr<CMapHeader> loadMapHeader(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const = 0;
 
 	/**
 	 * Saves map into VCMI format with name specified
@@ -83,8 +83,8 @@ public:
 
 	std::unique_ptr<CMap> loadMap(const ResourceID & name) const override;
 	std::unique_ptr<CMapHeader> loadMapHeader(const ResourceID & name) const override;
-	std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override;
-	std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override;
+	std::unique_ptr<CMap> loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override;
+	std::unique_ptr<CMapHeader> loadMapHeader(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override;
 	void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath) const override;
 	
 	/**
@@ -110,7 +110,7 @@ private:
 	 * @param size the size of the buffer
 	 * @return a unique ptr to the input stream class
 	 */
-	static std::unique_ptr<CInputStream> getStreamFromMem(const ui8 * buffer, int size);
+	static std::unique_ptr<CInputStream> getStreamFromMem(const uint8_t * buffer, int size);
 
 	/**
 	 * Gets a map loader from the given stream. It performs checks to test