⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pack.cpp

📁 liu7788414
💻 CPP
字号:
#pragma warning(disable :4786)
#include "stdafx.h"
#include "windows.h"
//#include "shlwapi.h"
#include "shlobj.h"
#include "objbase.h"
#include <assert.h>

#include <stdlib.h>
#include <assert.h>
#include <string>
#include <iostream>
#include <vector>
#include "estdio.h"
using namespace std;

extern "C"{
	HRESULT ResolveIt(HWND hwnd, LPCSTR lpszLinkFile, LPSTR lpszPath) ;
}

struct PakEntry{
	unsigned long nameHash; // hashValue of fileName.
	unsigned long start;	//*4 is the start address.
	unsigned long len;
};

struct Pak{
	long nPak;
	struct PakEntry aPak[0];
	//.. 
	//file1.
	//file2.
} *pak;

/* giving a file name, return a unique long to represent it. (a string hash function)
 * if 2 string has the same hash value, please change your file name( sorry :) )  
 */
unsigned long NameHash(const char* s)
{
	unsigned long h=0;
	const char *p;
	for(p = s; *p ; p ++) 
		h = ( h << 5 ) - h + *p;
  return h;
}

/* check if 2 string of a strings set has the same hash value, 
 * if so , please change your file name
 */
void IsCollision(vector<string>& names)
{
	int collision = 0;
	vector<string>::iterator i;
	for(i= names.begin(); i!=names.end(); i++){
		unsigned int nameHash = NameHash((*i).c_str());
		for(vector<string>::iterator j = names.begin(); j!= i; j++){
			if(nameHash == NameHash((*j).c_str())){
				cout << "Hash collision: "<< *i <<'\t' <<*j <<'\n';
				collision = 1;
			}
		}
	}
	if(collision)
		exit(-1);
}
/* in BREW, the file name are relative. convert absolute path name to relative name( relate to root)
 * for example, if root is		F:\\brewPrj\\brew\\san\\
 *				   name is		F:\\brewPrj\\brew\\san\\res\\a.dat
 * then the        result is							res\\a.dat
 */
string CalcRelativePath(string name ,string root)
{
		//the relative name. convert F:\\brewPrj\\brew\\san\\res\\a.dat to res\\a.dat
		string::size_type pos = name.find(root);
		if(pos == string::npos ){
			cout << "Cann't find root:"<< root <<" in "<< name <<'\n';
			assert(0);
			exit(-1);
		}
		
		return  name.substr(root.length(),name.length() - root.length());
}

/* giving a filename, return it's start offset in packaged file
 */
int FindHash(struct Pak* pak, string s,vector<string>& names,const char *root )
{
	struct PakEntry *p;

	for(p = pak->aPak;p- pak->aPak < pak->nPak; p++){
		string r = CalcRelativePath(s,root);
		if(p->nameHash == NameHash(r.c_str()))
			return p->start;
	}
	assert(0);
	return 0;
}

/* packing all file in names to a big file.
 * store name relate to root, 
 *	for each name
 *		compute name's hash value
 *		if conflict with previous have value
 *			prompt user to change name, exit
 *		start = temp.pak's len +3 &~3;
 *		len = name.len
 *		copy /b name to temp.pak
 *		aPak[i] ={nameHash, start/4,len}
 *	write pak to name.pak
 *	append temp.pak to name.pak
 *  remove temp.pak
 *	
 * NOTE: name rules:
 *		the name used to calculte hash value is relate to root, and have no .lzo posix, 
 *		so other module call fopen("res\\a.dat") will read res\\a.dat if not packaged,
 *		and will read res\\a.dat.lzo if packaged.
 */
void package(vector<string>& names, const char *root, const char *fileName)
{

	string rt(root);
	vector<string>::iterator i;
	int size = sizeof(pak) + names.size() * sizeof(struct PakEntry);
	pak = (struct Pak*)malloc(size);	
	pak->nPak = names.size();
	struct PakEntry *p;
	int start = size;
	FILE *log = efopen((string(fileName)+".txt").c_str(),"wt");
	//concate all file to tmp.pak
	FILE *tmp = efopen("tmp.pak","wb");
	for(p = pak->aPak,i= names.begin()	; i!=names.end(); p++, i++){
		long len;
		char *block;

		if( string::npos != (*i).find("_linkTo_") ){
			p->nameHash = 0;
			continue;
		}

		block = BinRead((*i+".lzo").c_str(), &len) ;

		
		p->len = len;
		len = (len+3)&~3;	//align to long
		efwrite(block,1,len,tmp); //write length should align to long
		
		string r = CalcRelativePath(*i,root);
		p->nameHash = NameHash(r.c_str());
		p->start = start>>2;
		fprintf(log, "%08x\t%d\t%d\t%s\n",p->nameHash, p->start<<2, p->len, (r+".lzo").c_str());
		start += len;
		free(block);
	}

	for(p = pak->aPak,i= names.begin()	; i!=names.end(); p++, i++){
		if(p->nameHash != 0)	continue;
		/* adding support for shortcuts
		 * if *i is A_linkTo_B 
		 *		
		 *		
		 *		p->nameHash = NameHash( RelativePath(A));
		 *		p->start    = B's start ( s must already in NameHash. )
		 *	so the first loop process all non link file, second loop process linked ones
		 */
		string r = CalcRelativePath(*i,root);
		string A = r;
		int pos = A.find("_linkTo_");
		assert(pos != string::npos);
		A[pos] = 0;
		p->nameHash = NameHash(A.c_str());
		
		string B = r.substr(pos+strlen("_linkTo_"));
		pos = (*i).find_last_of("\\");
		assert(pos != string::npos);
		string C=(*i).substr(0, pos+1);
		C += B;

		p->start = FindHash(pak,C,names,root);
		fprintf(log,"%s  link To %s\n",A.c_str(), B.c_str());
		
	}

	fclose(tmp);
	fclose(log);
	//insert pak at the begin of tmp.pak
	FILE *out = efopen(fileName,"wb");
	efwrite(pak,1,size,out);
	long tmplen;
	char *buff = BinRead("tmp.pak",&tmplen);
	efwrite(buff,1,tmplen,out);
	fclose(out);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -