Files
core/Common/3dParty/pole/testbed.cpp
Alexander.Trofimov beb64a6efa utf8 -> utf8 with BOM
2016-06-23 19:23:34 +03:00

547 lines
14 KiB
C++

// testbed.cpp: Take a directory and its contents, and create a Structured Storage File from it.
// Written using Windows - it should be portable to other environments with relatively modest changes.
// This was done mainly as a way to test POLE at various stages, but it has some utility on its own.
//
#include <iostream>
#include <fstream>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <list>
#include <string>
#include <io.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <direct.h>
#include "pole.h"
POLE::Storage* storage = 0;
bool DirectoryExists( const char* dirname ){
if( _access( dirname, 0 ) == 0 ){
struct stat status;
stat( dirname, &status );
return (status.st_mode & S_IFDIR) != 0;
}
return false;
}
void visit( int indent, POLE::Storage* storage, std::string path )
{
std::list<std::string> entries;
entries = storage->entries( path );
std::list<std::string>::iterator it;
for( it = entries.begin(); it != entries.end(); ++it )
{
std::string name = *it;
std::string fullname = path + name;
for( int j = 0; j < indent; j++ )
std::cout << " ";
POLE::Stream* ss = new POLE::Stream( storage, fullname );
std::cout << name;
if( ss )
if( !ss->fail() )std::cout << " (" << ss->size() << ")";
std::cout << std::endl;
delete ss;
if( storage->isDirectory( fullname ) )
visit( indent+1, storage, fullname + "/" );
}
}
bool extract( POLE::Storage* storage, const char* stream_name, const char* outfile )
{
POLE::Stream* stream = new POLE::Stream( storage, stream_name );
if( !stream )
{
printf("A stream could not be opened for %s.\n", stream_name);
return false;
}
if( stream->fail() )
{
printf("A stream failed for %s.\n", stream_name);
return false;
}
std::ofstream file;
file.open( outfile, std::ios::binary|std::ios::out );
unsigned char buffer[16];
for( ;; )
{
unsigned read = stream->read( buffer, sizeof( buffer ) );
file.write( (const char*)buffer, read );
if( read < sizeof( buffer ) ) break;
}
file.close();
delete stream;
return true;
}
void extractDir(POLE::Storage* storage, std::string outDir, std::string path, int &nFolders, int &nFiles)
{
const char *cOutDir = outDir.c_str();
if (DirectoryExists(cOutDir))
{
std::cout << "You should not specify a directory for output that already exists." << std::endl;
return;
}
_mkdir(cOutDir);
nFolders++;
std::list<std::string> entries;
entries = storage->entries( path );
std::list<std::string>::iterator it;
for( it = entries.begin(); it != entries.end(); ++it )
{
std::string name = *it;
std::string fullname = path + name;
if (storage->isDirectory(fullname))
{
std::string outdirchild = outDir + name;
extractDir(storage, outdirchild + "/", fullname + "/", nFolders, nFiles);
}
else
{
POLE::Stream* stream = new POLE::Stream(storage, fullname);
if( !stream )
{
printf("A stream could not be opened for %s.\n", fullname);
return;
}
if( stream->fail() )
{
printf("A stream failed for %s.\n", fullname);
return;
}
std::ofstream file;
std::string outfname = outDir + name;
const char *coutfname = outfname.c_str();
file.open(coutfname, std::ios::binary|std::ios::out);
unsigned long bytesLeft = stream->size();
unsigned char buffer[4096];
while(bytesLeft > 0)
{
unsigned long bytesToRead = sizeof( buffer );
if (bytesLeft < bytesToRead)
bytesToRead = bytesLeft;
unsigned read = stream->read( buffer, bytesToRead );
file.write( (const char*)buffer, read );
bytesLeft -= read;
if( read < bytesToRead )
break; //shouldn't happen, probably
}
file.close();
delete stream;
nFiles++;
}
}
}
bool AddFile2Storage(POLE::Storage* storage, std::string inFile, std::string name)
{
std::ifstream file;
const char *cinfname = inFile.c_str();
file.open(cinfname, std::ios::binary|std::ios::in);
// find size of input file
file.seekg( 0, std::ios::end );
long filesize = file.tellg();
file.seekg( 0 );
POLE::Stream* ss = new POLE::Stream( storage, name, true, filesize );
if( !ss )
{
printf("A stream could not be opened for %s.\n", name);
file.close();
return false;
}
if( ss->fail() )
{
printf("A stream failed for %s.\n", name);
file.close();
return false;
}
unsigned char buffer[4096];
int bytesRead = 0;
int bytesToRead;
for (;;)
{
bytesToRead = filesize - bytesRead;
if (bytesToRead <= 0)
break;
if (bytesToRead > 4096)
bytesToRead = 4096;
file.read((char *)buffer, bytesToRead);
ss->write(buffer, bytesToRead);
bytesRead += bytesToRead;
}
ss->flush();
delete ss;
file.close();
return true;
}
void AddDir2Storage(POLE::Storage* storage, std::wstring inDir, std::wstring name, int &nFolders, int &nFiles)
{
WIN32_FIND_DATA ffd;
HANDLE h;
std::wstring inDirLcl = inDir + "*";
std::wstring outNameLcl = name;
const wchar_t *cInDir = inDirLcl.c_str();
h = FindFirstFile(cInDir, &ffd);
if (h == INVALID_HANDLE_VALUE)
return;
nFolders++;
do
{
if (ffd.cFileName[0] == '.')
{
if (ffd.cFileName[1] == 0 || (ffd.cFileName[1] == '.' && ffd.cFileName[2] == 0))
continue;
}
outNameLcl = name + ffd.cFileName;
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
outNameLcl += "/";
inDirLcl = inDir + ffd.cFileName;
inDirLcl += "\\";
AddDir2Storage(storage, inDirLcl, outNameLcl, nFolders, nFiles);
}
else
{
std::ifstream file;
std::string infname = inDir + ffd.cFileName;
const char *cinfname = infname.c_str();
file.open(cinfname, std::ios::binary|std::ios::in);
// find size of input file
file.seekg( 0, std::ios::end );
long filesize = file.tellg();
file.seekg( 0 );
POLE::Stream* ss = new POLE::Stream( storage, outNameLcl, true, filesize );
unsigned char buffer[4096];
int bytesRead = 0;
int bytesToRead;
for (;;)
{
bytesToRead = filesize - bytesRead;
if (bytesToRead <= 0)
break;
if (bytesToRead > 4096)
bytesToRead = 4096;
file.read((char *)buffer, bytesToRead);
ss->write(buffer, bytesToRead);
bytesRead += bytesToRead;
}
ss->flush();
delete ss;
file.close();
nFiles++;
}
}
while (FindNextFile(h, &ffd) != 0);
}
void cmdOpen(std::list<std::string> &entries)
{
if (entries.size() < 1)
std::cout << "You must enter the name of an existing file formatted as structured storage." << std::endl;
else
{
if (storage != 0)
storage->close();
std::string ssName = entries.front();
entries.pop_front();
storage = new POLE::Storage(ssName.c_str());
bool bWrite = false;
bool bCreate = false;
if (entries.size() > 0)
{
std::string modifiers = entries.front();
for (unsigned idx = 0; idx < modifiers.size(); idx++)
{
char c = modifiers[idx];
if (c == 'c')
bCreate = true;
else if (c == 'w')
bWrite = true;
}
}
storage->open(bWrite, bCreate);
int result = storage->result();
if (result == POLE::Storage::Ok)
std::cout << "Ok" << std::endl;
else
{
delete storage;
storage = 0;
if (result == POLE::Storage::BadOLE)
std::cout << "BadOLE" << std::endl;
else if (result == POLE::Storage::NotOLE)
std::cout << "NotOLE" << std::endl;
else if (result == POLE::Storage::OpenFailed)
std::cout << "OpenFailed" << std::endl;
else
printf("Unrecognizable result - %d\n", result);
}
}
}
void cmdClose(std::list<std::string> &entries)
{
if (storage)
{
storage->close();
delete storage;
storage = 0;
}
}
void cmdStats(std::list<std::string> &entries)
{
if (storage)
{
unsigned int nDirs, nUUDirs, nBBs, nUUBBs, nSBs, nUUSBs;
storage->GetStats(&nDirs, &nUUDirs, &nBBs, &nUUBBs, &nSBs, &nUUSBs);
printf("%d Directory Entries, %d unused.\n", nDirs, nUUDirs);
printf("%d Big Blocks, %d unused.\n", nBBs, nUUBBs);
printf("%d Small Blocks, %d unused.\n", nSBs, nUUSBs);
}
}
void cmdVisit(std::list<std::string> &entries)
{
if (!storage)
std::cout << "No storage is opened." << std::endl;
else
{
if (entries.size() > 0)
visit(0, storage, entries.front());
else
visit(0, storage, "/");
}
}
void cmdExtract(std::list<std::wstring> &entries)
{
if (!storage)
std::cout << "No storage is opened." << std::endl;
else if (entries.size() < 2)
std::cout << "You must specify a path in the open storage to be extracted, and a destination file or folder." << std::endl;
else
{
std::wstring ssPath = entries.front();
entries.pop_front();
std::wstring filePath = entries.front();
if (storage->isDirectory(ssPath))
{
if (filePath[filePath.size()-1] != '/')
filePath += '/';
if (ssPath[0] != '/')
ssPath = '/' + ssPath;
if (ssPath[ssPath.size()-1] != '/')
ssPath += '/';
int nFiles = 0;
int nFolders = 0;
extractDir(storage, filePath, ssPath, nFolders, nFiles);
printf("%d folders and %d files were extracted.\n", nFolders, nFiles);
}
else
{
if (extract(storage, ssPath.c_str(), filePath.c_str()))
std::cout << "Ok" << std::endl;
}
}
}
void cmdAdd(std::list<std::wstring> &entries)
{
if (!storage)
std::cout << "No storage is opened." << std::endl;
else if (entries.size() < 2)
std::cout << "You must specify a path in the open storage to be created or modified, and a source file or folder." << std::endl;
else if (!storage->isWriteable())
std::cout << "The open storage cannot be modified." << std::endl;
else if (entries.front() != "/" && storage->exists(entries.front()))
std::cout << "The specified storage node already exists - to save it again, first delete it." << std::endl;
else
{
std::wstring ssPath = entries.front();
entries.pop_front();
std::wstring filePath = entries.front();
if (DirectoryExists(filePath.c_str()))
{
if (filePath[filePath.size()-1] != '/')
filePath += '/';
if (ssPath[0] != '/')
ssPath = '/' + ssPath;
if (ssPath[ssPath.size()-1] != '/')
ssPath += '/';
int nFiles = 0;
int nFolders = 0;
AddDir2Storage(storage, filePath, ssPath, nFolders, nFiles);
printf("%d folders and %d files were added.\n", nFolders, nFiles);
}
else
{
if (AddFile2Storage(storage, filePath, ssPath))
std::cout << "Ok" << std::endl;
}
}
}
void cmdDelete(std::list<std::string> &entries)
{
if (!storage)
std::cout << "No storage is opened." << std::endl;
else if (entries.size() < 1)
std::cout << "You must specify a path in the open storage to be deleted." << std::endl;
else if (!storage->isWriteable())
std::cout << "The open storage cannot be modified." << std::endl;
else
{
if (!storage->deleteByName(entries.front()))
std::cout << "The deletion failed." << std::endl;
else
std::cout << "Ok" << std::endl;
}
}
bool cmdQuit(std::list<std::string> &entries)
{
cmdClose(entries);
return true;
}
void cmdHelp(std::list<std::string> &entries)
{
std::cout << "You can enter any of the following commands. Note that they are case sensitive." << std::endl;
std::cout << "open filePath [modifier] - modifiers can be any combination of r, w, or c (create)" << std::endl;
std::cout << "visit [ssPath] - list contents of the structured storage, or of one leaf or node" << std::endl;
std::cout << "extract ssPath filePath - Extract the contents of one leaf" << std::endl;
std::cout << "add ssPath filePath - Add the contents of one leaf to the structured storage" << std::endl;
std::cout << "delete ssPath - Delete the leaf or node, and whatever it contains" << std::endl;
std::cout << "stats - show statistics for the open storage" << std::endl;
std::cout << "close" << std::endl;
std::cout << "quit" << std::endl;
}
std::list<std::string> clineParse(std::string inCmd)
{
std::list<std::string> outWords;
std::string oneWord;
char c;
int idx;
int maxIdx = inCmd.size();
bool bInQuote = false;
for (idx = 0; idx < maxIdx; idx++)
{
c = inCmd[idx];
if (bInQuote)
{
if (c == '\"')
{
outWords.push_back(oneWord);
oneWord.clear();
bInQuote = false;
}
else
oneWord+= c;
}
else
{
if (c == '\"' && oneWord.size() == 0)
bInQuote = true;
else if (c == ' ')
{
if (oneWord.size() != 0)
{
outWords.push_back(oneWord);
oneWord.clear();
}
}
else
oneWord+= c;
}
}
if (oneWord.size() != 0)
outWords.push_back(oneWord);
return outWords;
}
//int main(int argc, char* argv[])
//{
// if( argc > 1 )
// {
// std::cout << "Usage:" << std::endl;
// std::cout << argv[0] << " This takes no arguments - type help in the console window for information. " << std::endl;
// return 0;
// }
//
// std::string command;
// while (true)
// {
// std::getline(std::cin, command);
// std::list<std::string> entries = clineParse(command);
// if (entries.size() == 0)
// continue;
// std::string cmdWord = entries.front();
// entries.pop_front();
// if (cmdWord.compare("open") == 0)
// cmdOpen(entries);
// else if (cmdWord.compare("visit") == 0)
// cmdVisit(entries);
// else if (cmdWord.compare("extract") == 0)
// cmdExtract(entries);
// else if (cmdWord.compare("add") == 0)
// cmdAdd(entries);
// else if (cmdWord.compare("delete") == 0)
// cmdDelete(entries);
// else if (cmdWord.compare("stats") == 0)
// cmdStats(entries);
// else if (cmdWord.compare("close") == 0)
// cmdClose(entries);
// else if (cmdWord.compare("quit") == 0)
// {
// if (cmdQuit(entries))
// break;
// }
// else
// cmdHelp(entries);
// }
//#if 0
// std::list<std::string>::iterator it;
// for( it = entries.begin(); it != entries.end(); ++it )
// std::cout << *it << std::endl;
// open filename [modifier] (modifier can be r, w, c)
//visit [sspath]
//extract sspath fpath
//add sspath fpath
//delete sspath
//close
//
// std::string indir = argv[1];
// char* outfile = argv[2];
// if (indir[indir.length()-1] != '\\')
// indir += "\\";
// POLE::Storage* storage = new POLE::Storage(outfile);
// storage->open(true, true);
// AddDir2Storage(storage, indir, "/");
// storage->close();
// storage->open();
// visit(0, storage, "/");
// storage->close();
//#endif
//}