#include
#include
static char g_mem[5 * 1024 * 1024];
#define MORE 17
#define min(a, b) ((a) < (b) ? (a) : (b))
typedef struct _ResMap
{
char *pName;
int iPos;
int iLen;
int iOrgLen;
char *pData;
int iDstBegin;
} ResMap;
typedef struct _Item
{
ResMap *rm;
int next;
} Item;
int ReadFile(char *pName)
{
FILE *pFile = fopen(pName, "rb");
int n = 0;
char *p = g_mem;
while (1)
{
n = fread(p, 1, 10240, pFile);
if (n == 0)
break;
p += n;
}
fclose(pFile);
return p - g_mem;
}
int Hash(char *str, int n)
{
unsigned int val = 0;
n += MORE;
for (; *str; ++str)
{
val = val * 31 + *str;
}
return val % n;
}
static char g_hex[] = "0123456789abcdef";
void ChangeHex(char *pFileName, ResMap *pMapBuf, int iIsLast, int *piFrom)
{
int iLen = ReadFile(pFileName);
int nlen = strlen(pFileName) + 1;
int iRstLen = (iLen + nlen) * 5;
char *pMem = malloc(iRstLen);
char *pCur = pMem;
unsigned char *pSrc = (unsigned char *)g_mem;
int i = 0;
for (i = 0; i < nlen; i++, pCur += 5)
{
pCur[0] = '0';
pCur[1] = 'x';
pCur[2] = g_hex[(pFileName[i] >> 4) & 0xf];
pCur[3] = g_hex[pFileName[i] & 0xf];
pCur[4] = ',';
}
for (i = 0; i < iLen; i++, pCur += 5)
{
pCur[0] = '0';
pCur[1] = 'x';
pCur[2] = g_hex[(pSrc[i] >> 4) & 0xf];
pCur[3] = g_hex[pSrc[i] & 0xf];
pCur[4] = ',';
}
iLen += nlen;
iRstLen -= (iIsLast ? 1 : 0);
pMapBuf->pName = pFileName;
pMapBuf->iLen = iRstLen;
pMapBuf->pData = pMem;
pMapBuf->iOrgLen = iLen;
pMapBuf->iDstBegin = *piFrom;
*piFrom += iLen;
}
void WriteHead(FILE *pC)
{
char *p = "#include \n\n"
"typedef struct _ResMap {\n"
" int iPos;\n"
" int iDatLen;\n"
" short sNameLen;\n"
" short sNext;\n"
"} ResMap;\n\n";
fwrite(p, strlen(p), 1, pC);
}
void WriteFunc(FILE *pC, int n)
{
char *p = "static int Hash(const char *str)\n"
"{\n"
" unsigned int val = 0;\n"
" for (; *str; ++str)\n"
" val = val * 31 + *str;\n"
" return val % ";
fwrite(p, strlen(p), 1, pC);
char buf[10];
sprintf(buf, "%d;\n", n + MORE);
fwrite(buf, strlen(buf), 1, pC);
p = "}\n\n"
"void * LoadRes(const char* pName, int *piLen)\n"
"{\n"
" int i = 0;\n"
" if (!pName || !piLen)\n"
" return 0;\n\n"
" i = Hash(pName);\n"
" *piLen = 0;\n\n"
" while (i != -1) {\n"
" if (! g_map[i].iDatLen)\n"
" return 0;\n"
" char *pExName = g_dat + g_map[i].iPos;\n"
" if (strcmp(pName, pExName) == 0) {\n"
" *piLen = g_map[i].iDatLen;\n"
" return (g_dat + g_map[i].iPos + g_map[i].sNameLen);\n"
" }\n"
" i = g_map[i].sNext;\n"
" }\n"
" return 0;\n"
"}\n\n\n";
fwrite(p, strlen(p), 1, pC);
}
void WriteCnt(FILE *pC, ResMap *pMap, int iResNum)
{
int i = 0;
char *p = "static char g_dat[] = {";
fwrite(p, strlen(p), 1, pC);
for (; i < iResNum; i++)
{
int len = pMap->iLen;
char *dat = pMap->pData;
while (len > 0) {
fwrite("\n\t", 2, 1, pC);
fwrite(dat, min(len, 80), 1, pC);
len -= 80;
dat += 80;
}
++pMap;
}
fwrite("\n};\n\n", 4, 1, pC);
}
void WriteTail(FILE *pC, Item *pIt, int iResNum)
{
char tmp[100];
char name[100];
int iMn = iResNum + MORE;
sprintf(tmp, "static ResMap g_map[] = {");
fwrite(tmp, strlen(tmp), 1, pC);
int i = 0, line = 0;
fwrite("\n\t", 2, 1, pC);
for (; i < iMn; i++)
{
char *p = (i == iMn - 1) ? "" : ",";
if (pIt->rm)
{
int iLen = strlen(pIt->rm->pName) + 1;
sprintf(tmp, "{0x%x,0x%x,0x%x,%d}%s", pIt->rm->iDstBegin, pIt->rm->iOrgLen - iLen, iLen, pIt->next, p);
}
else
{
sprintf(tmp, "{0}%s", p);
}
line += strlen(tmp);
if (line > 80) {
fwrite("\n\t", 2, 1, pC);
line = strlen(tmp);
}
fwrite(tmp, strlen(tmp), 1, pC);
++pIt;
}
fwrite("\n};\n\n\n", 6, 1, pC);
}
static char ** GetFileName(int *pNum)
{
char **pList = malloc(1000 * sizeof(char *));;
char buf[100];
*pNum = 0;
char *p = g_mem;
int len = ReadFile("r.txt");
p[len] = '\0';
while (sscanf(p, "%s\n", buf) > 0)
{
pList[*pNum] = malloc(strlen(buf) + 1);
strcpy(pList[*pNum], buf);
if (*buf == '\0')
break;
(*pNum)++;
p += strlen(buf) + 1;
}
return pList;
}
int FindPos(Item *pIt, int start, char *name)
{
if (strcmp(pIt[start].rm->pName, name) == 0)
return -1;
int i = start, old ;
while (1)
{
int mi = pIt[i].next;
if (mi == -1)
{
old = i;
break;
}
i = mi;
}
i = 0;
while (1)
{
if (! pIt[i].rm)
break;
i++;
}
pIt[old].next = i;
return i;
}
int main()
{
int n = 0;
int mn = 0;
char **pNames = GetFileName(&n);
ResMap *pMap = malloc(sizeof(ResMap) * n);
mn = n + MORE;
Item *pIt = malloc(sizeof(Item) * mn);
memset(pIt, 0, sizeof(Item) * mn);
int i = 0, from = 0;
for (; i < mn; i++)
pIt[i].next = -1;
for (i = 0; i < n; i++)
{
ChangeHex(pNames[i], pMap + i, i == n - 1, &from);
int v = Hash(pNames[i], n);
if (! pIt[v].rm)
{
pIt[v].rm = pMap + i;
}
}
for (i = 0; i < n; i++)
{
int v = Hash(pNames[i], n);
int pos = FindPos(pIt, v, pNames[i]);
if (pos != -1)
{
pIt[pos].rm = pMap + i;
}
}
FILE *pC = fopen("R.c", "wb");
WriteHead(pC);
WriteCnt(pC, pMap, n);
WriteTail(pC, pIt, n);
WriteFunc(pC, n);
fclose(pC);
return 0;
}
本程序从r.txt中读取需要打包的资源文件名, 最终生成了一个R.c文件
将R.c与其它c文件一起编译即可。
r.txt文件格式如下所示:
abc.png
def.jpg
.....
每个文件名占一行。
生成的R.c文件内容大概是这样子的:
#include
typedef struct _ResMap {
int iPos;
int iDatLen;
short sNameLen;
short sNext;
} ResMap;
static char g_dat[] = {
0x6d,0x61,0x69,0x6e,0x2e,0x63,0x00,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,
0x3c,0x73,0x74,0x64,0x69,0x6f,0x2e,0x68,0x3e,0x0d,0x0a,0x23,0x69,0x6e,0x63,0x6c,
0x75,0x64,0x65,0x20,0x3c,0x73,0x74,0x72,0x69,0x6e,.....
};
static ResMap g_map[] = {
{0x8b90,0x32ef,0x7,-1},{0},{0x1ab4,0x70d3,0x9,0},{0},{0},{0},{0},{0},{0},{0},
{0},{0x0,0x1aad,0x7,-1},{0},{0},{0},{0xbe86,0x19,0x2,-1},.....
};
static int Hash(const char *str)
{
unsigned int val = 0;
for (; *str; ++str)
val = val * 31 + *str;
return val % 21;
}
void * LoadRes(const char* pName, int *piLen)
{
int i = 0;
if (!pName || !piLen)
return 0;
i = Hash(pName);
*piLen = 0;
while (i != -1) {
if (! g_map[i].iDatLen)
return 0;
char *pExName = g_dat + g_map[i].iPos;
if (strcmp(pName, pExName) == 0) {
*piLen = g_map[i].iDatLen;
return (g_dat + g_map[i].iPos + g_map[i].sNameLen);
}
i = g_map[i].sNext;
}
return 0;
}