You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
8.8 KiB
C++
309 lines
8.8 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
|
|
#include "ResourceCompiler_precompiled.h"
|
|
#include "ListFile.h"
|
|
#include "StringHelpers.h"
|
|
#include "TempFilePakExtraction.h"
|
|
#include "PathHelpers.h"
|
|
#include "IPakSystem.h"
|
|
#include "IResCompiler.h"
|
|
#include "IRCLog.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CListFile::CListFile(IResourceCompiler* pRC)
|
|
: m_pRC(pRC)
|
|
{
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CListFile::Process(
|
|
const string& listFile,
|
|
const string& formatList,
|
|
const string& wildcardList,
|
|
const string& defaultFolder,
|
|
std::vector< std::pair<string, string> >& outFiles)
|
|
{
|
|
std::vector<string> wildcards;
|
|
StringHelpers::Split(wildcardList, ";", false, wildcards);
|
|
for (size_t i = 0; i < wildcards.size(); ++i)
|
|
{
|
|
wildcards[i] = PathHelpers::ToPlatformPath(wildcards[i]);
|
|
}
|
|
|
|
std::vector<string> formats;
|
|
StringHelpers::Split(formatList, ";", false, formats);
|
|
for (size_t i = 0; i < formats.size(); ++i)
|
|
{
|
|
formats[i] = PathHelpers::ToPlatformPath(formats[i]);
|
|
}
|
|
if (formats.empty())
|
|
{
|
|
formats.push_back("{0}");
|
|
}
|
|
|
|
if (!listFile.empty() && listFile[0] == '@')
|
|
{
|
|
int splitter = listFile.find_first_of("|;,");
|
|
if (splitter < 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string zipFilename = listFile.substr(1, splitter - 1);
|
|
string listFilename = listFile.substr(splitter + 1);
|
|
zipFilename.Trim();
|
|
listFilename.Trim();
|
|
|
|
ParseListFileInZip(zipFilename, listFilename, formats, wildcards, defaultFolder, outFiles);
|
|
return true;
|
|
}
|
|
|
|
// Parse List File.
|
|
std::vector<string> lines;
|
|
if (!ReadLines(listFile, lines))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (size_t i = 0; i < lines.size(); ++i)
|
|
{
|
|
string line = lines[i];
|
|
|
|
// Line can either contain filename, folder & filename
|
|
// or a zip file + list file (ex: @Levels\AlienVessel\Level.pak|resourcelist.txt)
|
|
if (line[0] == '@')
|
|
{
|
|
// the line starts with '@' character, this means a zip file
|
|
|
|
line = line.substr(1); // erase @ character
|
|
|
|
const size_t splitter = line.find_first_of("|;,");
|
|
if (splitter == line.npos)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string zipFilename = line.substr(0, splitter);
|
|
string listFilename = line.substr(splitter + 1);
|
|
zipFilename.Trim();
|
|
listFilename.Trim();
|
|
|
|
ParseListFileInZip(zipFilename, listFilename, formats, wildcards, defaultFolder, outFiles);
|
|
}
|
|
else
|
|
{
|
|
if (!ProcessLine(line, formats, wildcards, defaultFolder, outFiles))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CListFile::ParseListFileInZip(
|
|
const string& zipFilename,
|
|
const string& listFilename,
|
|
const std::vector<string>& formats,
|
|
const std::vector<string>& wildcards,
|
|
const string& defaultFolder,
|
|
std::vector< std::pair<string, string> >& outFiles)
|
|
{
|
|
// Open zip file
|
|
IPakSystem* const pPakSystem = m_pRC->GetPakSystem();
|
|
const char* const pTempPath = m_pRC->GetTmpPath();
|
|
|
|
const string sFileInPak = string("@") + zipFilename + "|" + listFilename;
|
|
TempFilePakExtraction fileProxy(sFileInPak.c_str(), pTempPath, pPakSystem);
|
|
|
|
// Parse List File.
|
|
std::vector<string> lines;
|
|
if (!ReadLines(fileProxy.GetTempName(), lines))
|
|
{
|
|
RCLogWarning("List file %s not found in zip file %s", listFilename.c_str(), zipFilename.c_str());
|
|
return;
|
|
}
|
|
|
|
for (size_t i = 0; i < lines.size(); ++i)
|
|
{
|
|
if (!ProcessLine(lines[i], formats, wildcards, defaultFolder, outFiles))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CListFile::ProcessLine(
|
|
const string& line,
|
|
const std::vector<string>& formats,
|
|
const std::vector<string>& wildcards,
|
|
const string& defaultFolder,
|
|
std::vector< std::pair<string, string> >& outFiles)
|
|
{
|
|
string folderName;
|
|
string fileName;
|
|
|
|
{
|
|
// Line can either contain filename (in quotes or without them) or folder & filename (both in quotes).
|
|
|
|
const char* p0 = strchr(line.c_str(), '\"');
|
|
const char* p1 = (p0 ? strchr(p0 + 1, '\"') : 0);
|
|
const char* p2 = (p1 ? strchr(p1 + 1, '\"') : 0);
|
|
const char* p3 = (p2 ? strchr(p2 + 1, '\"') : 0);
|
|
if (p0 == 0)
|
|
{
|
|
// single filename without quotes
|
|
folderName = defaultFolder;
|
|
fileName = line;
|
|
}
|
|
else if (p1 && (p2 == 0))
|
|
{
|
|
// single filename in quotes
|
|
folderName = defaultFolder;
|
|
fileName = string(p0 + 1, p1);
|
|
}
|
|
else if (p3)
|
|
{
|
|
// folder & filename in quotes
|
|
folderName = string(p0 + 1, p1);
|
|
fileName = string(p2 + 1, p3);
|
|
}
|
|
else
|
|
{
|
|
RCLogError("Bad syntax of a row in list file");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (fileName.empty())
|
|
{
|
|
RCLogError("Filename is empty in a row of list file");
|
|
return false;
|
|
}
|
|
|
|
fileName = PathHelpers::ToPlatformPath(fileName);
|
|
folderName = PathHelpers::ToPlatformPath(folderName);
|
|
|
|
std::vector<string> tokens;
|
|
|
|
{
|
|
bool bMatchFound = false;
|
|
|
|
for (size_t i = 0; i < wildcards.size(); ++i)
|
|
{
|
|
if (StringHelpers::MatchesWildcardsIgnoreCase(fileName, wildcards[i]))
|
|
{
|
|
if (!StringHelpers::MatchesWildcardsIgnoreCaseExt(fileName, wildcards[i], tokens))
|
|
{
|
|
RCLogError("Unexpected failure in %s", __FUNCTION__);
|
|
return false;
|
|
}
|
|
bMatchFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!bMatchFound)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
for (size_t formatIndex = 0; formatIndex < formats.size(); ++formatIndex)
|
|
{
|
|
string str = formats[formatIndex];
|
|
|
|
size_t scanFromPos = 0;
|
|
for (;; )
|
|
{
|
|
const size_t startPos = str.find('{', scanFromPos);
|
|
if (startPos == str.npos)
|
|
{
|
|
break;
|
|
}
|
|
|
|
const size_t endPos = str.find('}', startPos + 1);
|
|
if (endPos == str.npos)
|
|
{
|
|
break;
|
|
}
|
|
|
|
const string indexStr = str.substr(startPos + 1, endPos - startPos - 1);
|
|
|
|
bool bBadSyntax = indexStr.empty();
|
|
for (size_t i = 0; i < indexStr.length(); ++i)
|
|
{
|
|
if (!isdigit(indexStr[i]))
|
|
{
|
|
bBadSyntax = true;
|
|
}
|
|
}
|
|
if (bBadSyntax)
|
|
{
|
|
RCLogError("Syntax error in element {%s} in input string %s", indexStr.c_str(), formats[formatIndex].c_str());
|
|
return false;
|
|
}
|
|
|
|
const int index = atoi(indexStr.c_str());
|
|
if ((index < 0) || (index > tokens.size()))
|
|
{
|
|
RCLogError("Bad index specified in {%s} in input string %s", indexStr.c_str(), formats[formatIndex].c_str());
|
|
return false;
|
|
}
|
|
|
|
const string& replaceWith = (index == 0) ? fileName : tokens[index - 1];
|
|
str = str.replace(startPos, endPos - startPos + 1, replaceWith);
|
|
scanFromPos = startPos + replaceWith.size();
|
|
}
|
|
|
|
outFiles.push_back(std::pair<string, string>(folderName, str));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CListFile::ReadLines(
|
|
const string& listFile,
|
|
std::vector<string>& lines)
|
|
{
|
|
FILE* f = nullptr;
|
|
azfopen(&f, listFile, "rt");
|
|
if (!f)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
char line[2048];
|
|
while (fgets(line, sizeof(line), f) != NULL)
|
|
{
|
|
if (line[0])
|
|
{
|
|
string strLine = line;
|
|
strLine.Trim();
|
|
if (!strLine.empty())
|
|
{
|
|
lines.push_back(strLine);
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
return true;
|
|
}
|