khanat-opennel-code/code/ryzom/common/src/game_share/file_description_container.cpp
2014-02-07 19:29:36 -08:00

282 lines
8.3 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//-------------------------------------------------------------------------------------------------
// includes
//-------------------------------------------------------------------------------------------------
#include "stdpch.h"
#include "nel/misc/path.h"
#include "nel/misc/algo.h"
#include "utils.h"
#include "file_description_container.h"
#ifdef NL_OS_WINDOWS
#include <time.h>
#include <sys/types.h>
//#include <sys/stat.h>
#include <stdio.h>
#endif
//-------------------------------------------------------------------------------------------------
// namespaces
//-------------------------------------------------------------------------------------------------
using namespace std;
using namespace NLMISC;
//-------------------------------------------------------------------------------------------------
// methods CFileDescription
//-------------------------------------------------------------------------------------------------
CFileDescription::CFileDescription(const string& name,uint32 time,uint32 size)
{
FileName=name;
FileTimeStamp=time;
FileSize=size;
}
bool CFileDescription::set(const string& name)
{
FileName=name;
// if the file doesn't exist then zero out time stamp and size and return false
if (!NLMISC::CFile::fileExists(name))
{
FileTimeStamp=0;
FileSize=0;
return false;
}
// setup timestamp and size for the file
FileTimeStamp=NLMISC::CFile::getFileModificationDate(name);
FileSize=NLMISC::CFile::getFileSize(name);
return true;
}
void CFileDescription::serial(NLMISC::IStream& stream)
{
stream.serial(FileName);
stream.serial(FileTimeStamp);
stream.serial(FileSize);
}
CSString CFileDescription::toString(uint32 maxFileNameLen) const
{
return NLMISC::toString("%*s (size: %u, time stamp: %s)",maxFileNameLen,FileName.c_str(),FileSize,IDisplayer::dateToHumanString(FileTimeStamp));
}
bool CFileDescription::operator<(const CFileDescription& other) const
{
return FileName<other.FileName;
}
//-------------------------------------------------------------------------------------------------
// methods CFileDescriptionContainer
//-------------------------------------------------------------------------------------------------
// add a specific file to the container
void CFileDescriptionContainer::addFile(const CFileDescription& fileDescription)
{
_FileDescriptions.push_back(fileDescription);
}
void CFileDescriptionContainer::addFile(const string& fileName, uint32 timeStamp, uint32 size)
{
CFileDescription& theFileDescription= vectAppend(_FileDescriptions);
theFileDescription.FileName= fileName;
theFileDescription.FileTimeStamp= timeStamp;
theFileDescription.FileSize= size;
}
void CFileDescriptionContainer::addFile(const string& fileName)
{
//#ifdef NL_OS_WINDOWS
//
// struct _stat buffer;
// uint32 result= _stat(fileName.c_str(),&buffer);
// if (result==0)
// {
// addFile(fileName, uint32(buffer.st_mtime), buffer.st_size);
// }
//
//#else
if (CFile::fileExists(fileName))
{
addFile(fileName,CFile::getFileModificationDate(fileName),CFile::getFileSize(fileName));
}
//#endif
}
void CFileDescriptionContainer::addFileSpec(const string& fileSpec,bool recurse)
{
// extract path and wildcard from fileSpec
string theWildcard=NLMISC::CFile::getFilename(fileSpec);
string path=NLMISC::CFile::getPath(fileSpec);
std::vector<std::string> wildcards;
wildcards.push_back(theWildcard.empty()? "*": theWildcard);
addFiles(path,wildcards,recurse);
}
void CFileDescriptionContainer::addFiles(const std::string& directory, const std::vector<std::string>& wildcards, bool recurse)
{
H_AUTO(fdcAddFiles)
std::string path= directory.empty()? ".": directory;
// build a list of all files in the matching directory
vector<string> rawFileNames;
{
H_AUTO(fdcAddFilesGetPathContents)
NLMISC::CPath::getPathContent(path.c_str(),recurse,false,true,rawFileNames);
}
// extract the files that match the given wildcard and build a result vector
{
H_AUTO(fdcAddFilesTestWildcards)
for (uint32 i=(uint32)rawFileNames.size();i--;)
{
uint32 j;
for (j=0;j<wildcards.size();++j)
{
if (testWildCard(NLMISC::CFile::getFilename(rawFileNames[i]),wildcards[j]))
break;
}
if (j!=wildcards.size())
{
H_AUTO(fdcAddFilesGetFileProperties)
addFile(rawFileNames[i]);
}
}
}
}
void CFileDescriptionContainer::addFiles(const std::string& directory, const NLMISC::CVectorSString& wildcards, bool recurse)
{
// note that a CVectorSString is guaranteed to be bitwise identical to a vector of std::string
addFiles(directory,reinterpret_cast<const std::vector<std::string>&>(wildcards),recurse);
}
void CFileDescriptionContainer::addFiles(const CFileDescriptionContainer& other)
{
// note: the following can doubtless be done with a single tsl operation (eg +=)
// but I don't have an stl refference to hand so doing it longhand...
// make room in the file description container for the data from the other object
uint32 otherSize= (uint32)other._FileDescriptions.size();
uint32 oldSize= (uint32)_FileDescriptions.size();
uint32 newSize= oldSize + otherSize;
_FileDescriptions.resize(newSize);
// prepare to copy from one vector to the other
TFileDescriptions::iterator destIt = _FileDescriptions.begin()+oldSize;
TFileDescriptions::const_iterator srcIt = other._FileDescriptions.begin();
TFileDescriptions::const_iterator itEnd = other._FileDescriptions.end();
// do the copy
while (srcIt!=itEnd)
{
*destIt= *srcIt;
++srcIt;
++destIt;
}
}
void CFileDescriptionContainer::display(NLMISC::CLog* log) const
{
nlassert(log!=NULL);
// determine the length of the longest file name
uint32 longest=10;
for (uint32 i=0;i<_FileDescriptions.size();++i)
longest=max(longest,(uint32)_FileDescriptions[i].FileName.size());
// build a vector of strings to display
vector<string> lines;
for (uint32 i=0;i<_FileDescriptions.size();++i)
lines.push_back(NLMISC::toString("%-*s %12d %s",longest,
_FileDescriptions[i].FileName.c_str(),
_FileDescriptions[i].FileSize,
IDisplayer::dateToHumanString(_FileDescriptions[i].FileTimeStamp)));
// sort the lines to make a nice alphabetical list
sort(lines.begin(),lines.end());
// display a nice banner
log->displayNL("%-*s %12s %12s",longest,"File_Name","File_Size","File_Time");
// display the file list
for (uint32 i=0;i<_FileDescriptions.size();++i)
log->displayNL(lines[i].c_str());
}
void CFileDescriptionContainer::serial(NLMISC::IStream& stream)
{
stream.serialCont(_FileDescriptions);
}
uint32 CFileDescriptionContainer::size() const
{
return (uint32)_FileDescriptions.size();
}
bool CFileDescriptionContainer::empty() const
{
return _FileDescriptions.empty();
}
void CFileDescriptionContainer::clear()
{
_FileDescriptions.clear();
}
const CFileDescription& CFileDescriptionContainer::operator[](uint32 idx) const
{
return (_FileDescriptions[idx]);
}
CFileDescription& CFileDescriptionContainer::operator[](uint32 idx)
{
return (_FileDescriptions[idx]);
}
// remove the 'n'th element from a file description container
void CFileDescriptionContainer::removeFile(uint32 idx)
{
BOMB_IF(idx>=_FileDescriptions.size(),"trying to remove files beyond the end of the file description vector",return);
_FileDescriptions[idx]=_FileDescriptions.back();
_FileDescriptions.pop_back();
}
// remove the provided string if found at the beginning of FileName
void CFileDescriptionContainer::stripFilename(const std::string& header)
{
for (std::vector<CFileDescription>::iterator it=_FileDescriptions.begin(); it!=_FileDescriptions.end(); ++it)
{
it->stripFilename(header);
}
}
//-------------------------------------------------------------------------------------------------